I have an AngularJS 1.6 app that looks like this:
angular.module('app').component('parent', {
template: '
<parent>
<display options="ctl.options"></display>
<controls options="ctl.options"></controls>
</parent>',
controller: function() {
this.options = { x: 100, y: 0.2 };
},
controllerAs: 'ctl',
bindToController: true
});
I'd like to use inputs in controls
component to modify properties of the options
object, so that changes are reflected in display
(but without rewriting entire object each time one property has been changed).
How can I do it? Even if I set options to two-way binding in controls
, display
is not updated and $onChanges
does not fire.
It can be easily accomplished with $watch or messages, but I can't figure out a proper component-centric way to do it.
A declarative way to do it would be to have a factory store the data, and pass the factory in to each controller. When either controller/component updates the state, it'll be reflected in the other controller/component.
var app = angular.module('app', []);
app.factory('Options', function(){
return {
data: {
x: 100,
y: 0.2
}
};
});
app.controller('DisplayCtrl', function($scope, Options){
$scope.options = Options.data;
});
app.controller('ControlsCtrl', function($scope, Options){
$scope.options = Options.data;
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app">
<div ng-controller="DisplayCtrl">
<p>x: {{ options.x }}</p>
<p>y: {{ options.y }}</p>
</div>
<div ng-controller="ControlsCtrl">
<label>
x: <input type="number" ng-model="options.x">
</label>
<label>
y: <input type="number" ng-model="options.y">
</label>
</div>
</div>
See Share data between AngularJS controllers for more thoughts. I think https://stackoverflow.com/a/25145593/1927876 is the best answer because it is so declarative and easy to reason about, and is what I base my answer here on.