I've been upgrading my custom directives to the new component architecture. I've read that components do not support watchers. Is this correct? If so how do you detect changes on an object? For a basic example I have custom component myBox
which has a child component game with a binding on the game . If there is a change game within the game component how do I show an alert message within the myBox? I understand there is rxJS method is it possible to do this purely in angular? My JS FIDDLE JS FIDDLE
JS
var app = angular.module('myApp', []);
app.controller('mainCtrl', function($scope) {
$scope.name = "Tony Danza";
});
app.component("myBox", {
bindings: {},
controller: function($element) {
var myBox = this;
myBox.game = 'World Of warcraft';
//IF myBox.game changes, show alert message 'NAME CHANGE'
},
controllerAs: 'myBox',
templateUrl: "/template",
transclude: true
})
app.component("game", {
bindings: {game:'='},
controller: function($element) {
var game = this;
},
controllerAs: 'game',
templateUrl: "/template2"
})
HTML
<div ng-app="myApp" ng-controller="mainCtrl">
<script type="text/ng-template" id="/template">
<div style='width:40%;border:2px solid black;background-color:yellow'>
Your Favourite game is: {{myBox.game}}
<game game='myBox.game'></game>
</div>
</script>
<script type="text/ng-template" id="/template2">
<div>
</br>
Change Game
<textarea ng-model='game.game'></textarea>
</div>
</script>
Hi {{name}}
<my-box>
</my-box>
</div><!--end app-->
I'm late. But it can help to another people.
To anyone interested in my solution, I end up resorting to RXJS Observables, which what you will have to use when you get to Angular 2. Here is a working fiddle for communications between components, it gives me more control on what to watch.
JS FIDDLE RXJS Observables
Really Nice accepted answer, but I might add that you can use also the power of events ( a bit like in Qt signal / slots if you will ).
An event is broadcast :
$rootScope.$broadcast("clickRow", rowId)
by any parent ( or even children controller ). Then in your controller you can handle the event like this :You can also add some logging on that like this ( taken from here : https://stackoverflow.com/a/34903433/3147071 )
A small heads-up regarding the use of
ng-change
, as recommended with the accepted answer, together with an angular 1.5 component.In case you need to watch a component that
ng-model
andng-change
do not work, you can pass the parameters as:Markup in which component is used:
Component js:
Component markup:
Available in IE11, MutationObserver https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver. You need to inject $element service into controller which semi-breaks DOM/controller separation, but I feel that this is a fundamental exception (ie. flaw) in angularjs. Since hide/show is async, we need on-show callback, that angularjs & angular-bootstrap-tab do not provide. It also requires that u know which specific DOM element u want to observe. I used following code for angularjs controller to trigger Highcharts chart reflow on-show.
Writing Components without Watchers
This answer outlines five techniques to use to write AngularJS 1.5 components without using watchers.
ng-change
Directive$onChanges
Life-cycle Hook$doCheck
Life-cycle HookUse the
ng-change
DirectiveYou can use the
ng-change
directive to react to input changes.And to propagate the event to a parent component, the event handler needs to be added as an attribute of the child component.
JS
And in the parent component:
This is the preferred method going forward. The AngularJS strategy of using
$watch
is not scalable because it is a polling strategy. When the number of$watch
listeners reaches around 2000, the UI gets sluggish. The strategy in Angular 2 is to make the framework more reactive and avoid placing$watch
on$scope
.Use the
$onChanges
Life-cycle HookWith version 1.5.3, AngularJS added the
$onChanges
life-cycle hook to the$compile
service.From the Docs:
The
$onChanges
hook is used to react to external changes into the component with<
one-way bindings. Theng-change
directive is used to propogate changes from theng-model
controller outside the component with&
bindings.Use the
$doCheck
Life-cycle HookWith version 1.5.8, AngularJS added the
$doCheck
life-cycle hook to the$compile
service.From the Docs:
Intercomponent Communication with
require
Directives can require the controllers of other directives to enable communication between each other. This can be achieved in a component by providing an object mapping for the require property. The object keys specify the property names under which the required controllers (object values) will be bound to the requiring component's controller.
For more information, see AngularJS Developer Guide - Intercomponent Communicatation
Push Values from a Service with RxJS
Build a service with RxJS Extensions for Angular.
Then simply subscribe to the changes.
Clients can subscribe to changes with
DataService.subscribe
and producers can push changes withDataService.set
.The DEMO on PLNKR.