如何在AngularJS中从父组件中分解子组件中的函数?

时间:2017-03-28 14:29:18

标签: javascript angularjs

使用&在子组件中绑定我们可以运行作为父组件控制器一部分的函数。我正在努力在相反的方向上做同样的事情 - 当父组件中发生某些事情时,子组件运行功能。

mapComponentmainComponent的直接孩子。 mapComponent会显示带有一些标记的全屏谷歌地图(使用NgMap)。 mainComponent处理登录和注册。如果用户开始注册,我需要在mapComponent中运行删除所有标记并附加地图事件的功能,以便用户可以点击地图显示他居住的地方,并且可以在注册时保存这些坐标。

仅举例来说,这不是复杂的,这里是我在搜索stackoverflow时找到的plunker代码:

var app = angular.module('plunker', []);

app.controller('RootController', function() {});

app.component('parentComponent', {
  template: `
    <h3>Parent component</h3>
    <a class="btn btn-default btn-sm" ng-click="$ctrl.click()">Notify Child</a>
    <span data-ng-bind="$ctrl.childMessage"></span>
    <child-component on-change="$ctrl.notifiedFromChild(count)" message="$ctrl.message"></child-component>
  `,
  controller: function() {
    var ctrl = this;
    ctrl.notifiedFromChild = function(count) {
      ctrl.childMessage = "From child " + count;
    }
    ctrl.click = function() {
      ctrl.message = Math.random()
    }
  },
  bindings: {}
});

app.component('childComponent', {
  template: `
    <h4>Child component</h4>
    <a class="btn btn-default btn-sm" ng-click="$ctrl.click()">Notify Parent</a>
    <span>{{$ctrl.parentMessage}}</span>
  `,
  controller: function() {
    var ctrl = this;
    ctrl.counter = 0;
    ctrl.click = function() {
      ctrl.onChange({
        count: ++ctrl.counter
      });
    }
  },
  bindings: {
    onChange: '&',
    parentMessage: '<message'
  }
});

在此示例中,通过单击父组件中的按钮,我可以通过数据绑定更改子组件中的parentMessage值。但是,当父组件要求时,我希望找到一种子组件自行更改此值的方法。

3 个答案:

答案 0 :(得分:1)

您可以使用BroadCast和on mechanism

$scope.startScanner = function() {

    $rootScope.$broadcast('scanner-started');
}

然后接收,使用控制器的$scope

$scope.$on('scanner-started', function(event, args) {

    // do what you want to do
});

如果你想要,你可以在$ broadcast时传递参数:

$rootScope.$broadcast('scanner-started', { any: {} });

然后收到它们:

$scope.$on('scanner-started', function(event, args) {

    var anyThing = args.any;
    // do what you want to do
});

答案 1 :(得分:1)

一种可能的解决方案是在父级中创建一个register函数,如下所示:

ctrl.register = function(child){
    ctrl.childCtrl = child;
}

然后使用常规回调绑定将此register函数传递给子进程,并让子进程调用它。像这样:

app.component('childComponent', {
    bindings: {
        registerParent: '&'
    }
    controller: function() {
        var ctrl = this;

        // Register the child controller with the parent.
        ctrl.registerParent({childRef: ctrl});

        ctrl.childFunction = function(message) {
            console.log('Child function: ' + message);
        }
    },
    // ...and so on
});

然后将其传递给模板

<child-component register-parent="$ctrl.register(childRef)" />

在此之后,您可以使用childRef变量从父级调用子控制器的任何功能。因此,例如在您的父母中,您可以这样做:

ctrl.childRef.childFunction("called from parent")

并且应该将以下内容记录到控制台中:Child function: called from parent

我创建了Plunker to show this working.

答案 2 :(得分:0)

您可以尝试双向绑定。

您的子组件将具有新的绑定:

bindings: {
    onChange: '&',
    parentMessage: '<message',
    callChild: '='
  }

并在您的子组件中使用函数

填充该绑定
ctrl.callChild = function() {
    ctrl.parentCalled = true;
}

并在您的父母中调用该函数。我已经更新了你的plunker来做我刚刚解释过的事情。

plunker