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
Communicating Events from Parent to Child in AngularJS Components
Publish Directive $API Using Expression Binding
To allow parent components to communicate events to a child component, have the child publish an API:
JS
The above example invokes the Angular Expression defined by the
grid-on-init
attribute with its API exposed as$API
. The advantage to this approach is that the parent can react to child initialization by passing a function to the child component with the Angular Expression.From the Docs:
-- AngularJS Comprehensive Directive API -- scope
As a convention, I recommend prefixing local variables with
$
to distinguish them from parent variables.Alternately use Bi-Directional Binding
NOTE: To ease the transition to Angular 2+, avoid the use of bi-directional
=
binding. Instead use one-way<
binding and expression&
binding. For more information, see AngularJS Developer Guide - Understanding Components.To allow parent components to communicate events to a child component, have the child publish an API:
In the above example, the
grid-component
uses bindings to publish its API onto the parent scope using theapi
attribute.Then the parent component can invoke the child
save
function using the published API:The DEMO on PLNKR.
Here is an easy way: http://morrisdev.com/2017/03/triggering-events-in-a-child-component-in-angular/
basically, you add a bound variable called "command" (or whatever you want) and use the $onChanges to pay attention to changes of that variable and trigger whatever event it says to trigger manually.
I personally like to put all my variables into an object called "settings" and send that to all my components. However, a change to a value within an object does NOT trigger the $onChanges event, so you NEED to tell it to trigger the event with a flat variable.
I'd say it is not the "proper" way to do it, but it sure is a lot easier to program, a lot easier to understand, and a lot easier to convert to A2 later on down the road.
I faced with same question. What do you think about this approach: to use inheritance via
require
instead of Bi-Directional Binding?http://plnkr.co/edit/fD1qho3eoLoEnlvMzzbw?p=preview
Or we can define setter method for parent to make it more explicit.
http://plnkr.co/edit/jmETwGt32BIn3Tl0yDzY?p=preview