【问题标题】:Call a Directive Controller's method from Parent Controller in AngularJS从 AngularJS 中的父控制器调用指令控制器的方法
【发布时间】:2015-11-23 17:25:55
【问题描述】:

我正在使用 AngularJS,并且我有一个指令,它有自己的控制器。它继承了父控制器的范围。

例如,考虑以下问题:

function ParentCtrl() {
    $scope.aMethod = function() {
        // DO SOMETHING
    };
}

function ChildCtrl() {
    $scope.bMethod = function() {
        // DO SOMETHING ELSE
    }
}  

现在,ParentCtrl() 的 $scope.aMethod 由 ng-click 指令触发。我想做的是调用 ChildCtrl() 的$scope.bMethod。我该怎么做?

编辑:更多信息。与 ParentCtrl 关联的模板有一个按钮和多个指令。每个指令加载具有不同输入集的表单。当点击ParentCtrl Template中的按钮时,指令会以ng-switch onng-switch-when的方式依次加载。
当用户单击按钮时,属于指令的 ChildCtrl 用于将数据存储在各自的表单中。
因此,当单击按钮时:
1. ChildCtrl 保存与当前已加载的指令关联的模型。
2. ParentCtrl 加载系列中的下一个指令。
ng-click 绑定到与 ParentCtrl 关联的按钮。但是当单击该按钮时,ChildCtrl 还需要执行一些操作(保存表单数据)。如何做到这一点?

【问题讨论】:

  • 你不能。但是父范围属性上的服务或$watch 可以完成同样的事情。您能否提供有关您的用例的更多详细信息?
  • @JoshDavidMiller 当然。编辑了我的问题以反映相同的...
  • 你能发布一个识别核心问题空间的超级简单的 plunker 吗?

标签: angularjs


【解决方案1】:

请看以下内容。

我正在使用$broadcast 的概念。 我已经厌倦了复制您给出的场景,例如父控制器、带有自己的控制器的子指令等:

var animateAppModule = angular.module('animateApp', [])
animateAppModule.controller('tst', function($scope) {
  $scope.test = function() {
    $scope.$broadcast('clickMessageFromParent', {
      data: "SOME msg to the child"
    })
  }
}).directive('myDirective', function() {
  return {
    controller: function($scope) {

    },
    link: function($scope, element) {
      $scope.$on('clickMessageFromParent', function(scopeDetails, msgFromParent) {
        //console.log(msgFromParent)
        element[0].innerHTML = msgFromParent.data;
      })
    }
  }
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-controller="tst">
  <input type="button" ng-click="test()" value="click" />
  <div my-directive="somvalue"></div>
</div>

JSFiddle

【讨论】:

  • 我还没有尝试过,但我发现这个有问题。我有多个指令会按顺序加载,即当点击按钮时,会加载一个新指令。如果所有指令都响应clickMessageFromParent 事件,那么它将不可行。我只希望当前的子控制器响应 - 会这样吗?
  • 只需将监听器附加到您想从父级监听的指令..
  • 这非常适合从控制器调用指令。
  • 通过 boradcast 调用子控制器方法是个好主意吗?我们不应该使用注射等吗?
【解决方案2】:

这类似于 rajkamal 所说的,因为您需要使用广播...但是您需要动态更改广播以针对您需要的任何孩子。

Here is a plunker showing an example

这是代码:

app.controller('MainCtrl', function($scope) {

  // a method that broadcasts to a selected child.
  $scope.broadcastToSelectedChild = function (){
    $scope.$broadcast('call-' + $scope.broadcastTo);
  };
});

app.directive('testDir', function (){
  return {
    restrict: 'E',
    scope: {
      'name': '@'
    },
    template: '<div>{{name}} called: {{called}}</div>',
    link: function(scope, elem, attr) {

      scope.called = false;

      //a child function to call.
      scope.childFunction = function (){
        scope.called = true;
      };

      //set up the name to be used as the listened to event.
      var removeOn;
      scope.$watch('name', function(v) {
        if(removeOn) removeOn();
        removeOn = scope.$on('call-' + scope.name, function (){
            scope.childFunction();
          });
      });
    }
  };
});

这里是 HTML:

  <div ng-controller="MainCtrl">
    <test-dir name="test1"></test-dir>
    <test-dir name="test2"></test-dir>
    <test-dir name="test3"></test-dir>
    <select ng-model="broadcastTo" ng-options="x as x for x in ['test1', 'test2', 'test3']"></select>
    <button ng-click="broadcastToSelectedChild()">test</button>
  </div>

我在这里所做的是创建一种机制,通过该机制我可以命名我的指令,然后按名称向它们广播。如果代码不是自我解释的,请告诉我。我希望这会有所帮助。

【讨论】:

    猜你喜欢
    • 2015-03-22
    • 1970-01-01
    • 1970-01-01
    • 2013-03-15
    • 1970-01-01
    • 1970-01-01
    • 2013-01-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多