首页 > 解决方案 > 如何使用 Angularjs 从具有父路由控制器的页面获取数据到自定义指令?

问题描述

我正在使用 Angularjs 1.4x,并且我有一个页面,其中声明了这样的控制器:

$stateProvider
        .state('myPage', {
            url: '/my-page',
            templateUrl: templateUrl,
            controller: 'searchCtrl', ...

在那个页面上,我有一个名为 myDirective 的指令,它有一个带有 ng-click 的按钮,它将一些文本作为参数发送回指令控制器。我要做的是在用户单击按钮时将该参数值返回给指令,然后调用另一个控制器来获取该参数值并打开一个模式。

如果我使用 $scope,我可以从 searchCtrl 获取值,但我一直无法找到一种方法来让指令接收参数值。过去,我会将按钮放在模板中,但这里的按钮已经在 myPage.html 页面中。

我现在知道我不能在页面上使用 ng-controller,因为它已经有一个来自 $route 的控制器,即 searchCtrl。那么这样做的正确方法是什么?

这是我的代码,但我没有 ui-router ,但我不知道这是否重要,以及plunker

索引.html

<!DOCTYPE html>
<html>
  <head>
    <script data-require="angular.js@1.4.2" data-semver="1.4.2" src="https://code.angularjs.org/1.4.2/angular.js"></script>
    <link rel="stylesheet" href="style.css" />
    <script src="script.js"></script>
  </head>

  <body>
    <div id="app" ng-app="app">
    <div ng-controller="myCtrl">
          <my-directive ctrl-fn="ctrlFn"></my-directive> 
        </div>
      </div>

  </body>
</html>

我的页面.html

<div>
  <button ng-click="ctrlFn({param: 'hello'})">Click Here</button>
</div>

脚本.js

// Code goes here
var app = angular.module('app', []);
app.controller('myCtrl', function($scope){

  $scope.ctrlFn = function(param) {
      console.log("param is: " + JSON.stringify(param));
  };  
});

function newCtrl($scope) {
  //How can I call this function from inside the directive and pass in param?
  //Do something here
}

app.directive('myDirective', function() {
  return {
    restrict: 'E',
    scope: {
      ctrlFn: '&'
    },
   templateUrl: "./myPage.html",
    link: function(scope, element, attributes, controller) {
      scope.ctrlFn = scope.ctrlFn();

    }
  };
});

关于如何正确实施这一点的任何想法?

标签: angularjsangularjs-directiveangular-ui-routerangularjs-scope

解决方案


如果您可以将回调函数放入服务中,则可以执行以下操作:

var app = angular.module('app', []);
app.controller('mainCtrl', function($scope, newCtrl) {

  $scope.ctrlFn = function(param) {
    console.log("param is: " + JSON.stringify(param));
    newCtrl.notify(param);
  };
  console.log(" $scope.ctrlFn is: " + JSON.stringify($scope.ctrlFn));
});

function newCtrl() {
  return {
    notify: notify
  }

  function notify(param) {
    console.log("In newCtrl.notify, param is: " + JSON.stringify(param));
  };
}

app.directive('myDirective', function() {
  return {
    restrict: 'E',
    scope: {
      ctrlFn: '&'
    },
    templateUrl: "./myPage.html",
    link: function(scope, element, attributes, controller) {
      scope.ctrlFn = scope.ctrlFn();
    }
  };
});

app.factory("newCtrl", newCtrl);

(不过我不会真正称它为 newCtrl,因为它现在是一项服务)。

请参阅:https ://plnkr.co/edit/5N957XYFPZVndr75lQ8N?p=preview

如果您需要$scope在服务中,您可以将其作为参数传递。

如果您不需要 in 中的匿名函数mainCtrl,您可以更进一步,执行以下操作:

$scope.ctrlFn = newCtrl.notify;

编辑:

有点复杂(我为将我的所有参数/属性命名为 ngModel 表示歉意),但这是我倾向于做的事情,当我想要一个从页面控制器获取传递数据的指令时,该指令将打开一个模态,并基于用户交互,将通过指令更新回初始控制器/视图的数据(模型)的值更改:

  1. 我创建了一个指令,在该指令上我将ng-model(主控制器/页面)视图中的属性设置为控制器上的属性$scope

  2. 该指令可以在隔离范围内访问(读取和写入)此值,然后可以在模板中使用它。

  3. 在用户操作时,该指令打开一个模态并通过resolve引导modal.open方法的属性将值传递给模态控制器。我通常会传入多个值,因此我将它们全部放在一个“选项”复合参数中。

  4. 模态控制器在注入模态控制器时接收此值(在选项中)[解析属性在模态控制器请求时提供它]。

  5. 然后模态控制器可以将此值设置到模态视图中(通过模态$scope/ vm)。通常,我在模态对话框中加载数据,例如显示项目列表供用户选择。

  6. Close事件/动作上,我将值(是否由用户交互更改)返回给调用者 [作为指令的控制器],这会将其设置回指令的 [隔离] 范围,这实质上会更新 mainController 上的属性,如它通过=值绑定。

https://plnkr.co/edit/qAa1pOwigCgJ99Lx6vsj?p=preview


推荐阅读