Luca Trazzi Luca Trazzi - 6 months ago 232
AngularJS Question

Communicating Events from Parent to Child in AngularJS Components

in the new project I'm working on I've started using the components instead of directives.

however, I've encountered an issue where I cannot find a concrete standard way to do it.

It's easy to notify an event from child to parent, you can find it on my plunkr below, but what's the correct way to notify a event from parent to child?

Angular2 seems to solve this issue by using something like this: https://angular.io/docs/ts/latest/cookbook/component-communication.html#!#parent-to-child-local-var
But I don't tink there's a possibilty to define a "pointer" to the child component like the example did with #timer

In order to mantain a possible easy conversion to Angular2 I want to avoid:


  • event emitting (emit and broadcast from the scopes)

  • using the require from the child (and then add a callback to the parent..UGLY)

  • using a one-way binding, injecting the scope in the child and then "watch" this property.. MORE UGLY



Example code:

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)"></child-component>
`,
controller: function() {
var ctrl = this;
ctrl.notifiedFromChild = function(count){
ctrl.childMessage = "From child " + count;
}
ctrl.click = function(){
}
},
bindings: {
}
});

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


You can find an example here:

http://plnkr.co/edit/SCK8XlYoYCRceCP7q2Rn?p=preview

This is a possible solution I created

http://plnkr.co/edit/OfANmt4zLyPG2SZyVNLr?p=preview

where the child requires the parent, and then child sets a parent reference to the child... now parent can use the child... ugly but it's like angular2 example above

Answer

Communicating Events from Parent to Child in AngularJS Components

To allow parent components to communicate events to a child component, have the child publish an API:

<grid-component api="$ctrl.gridApi"></grid-component>

In the above example, the grid-component uses bindings to publish its API onto the parent scope using the api attribute.

app.component('gridComponent', {
  //Create API binding
  bindings: {api: "="},
  template: `
    <h4>Grid component</h4>
    <p> Save count = {{$ctrl.count}}
  `,
  controller: function() {
    var ctrl = this;
    this.$onInit = function() {
        ctrl.count = 0;
        ctrl.api = {};
        //Publish save function
        ctrl.api.save = save;
    };
    function save(){
      console.log("saved!");
      ctrl.count++;
    }
  }
});

Then the parent component can invoke the child save function using the published API:

ctrl.click = function(){
  console.log("Search clicked");
  ctrl.gridApi.save();
}

The DEMO on PLNKR.

Comments