AngularJS has a DOM based controller inheritance, as mentioned in the angular Docs.
<div ng-controller="BaseController">
<p>Base Controller Value: {{value}}</p>
<button ng-click="updateValue()">Update In Base</button>
<div ng-controller="DerivedController">
<p>Derived Controller Value: {{value}}</p>
<button ng-click="updateValue()">Update In Derived</button>
</div>
</div>
The scope variable "value" is present only in the BaseController. Based on this, while changing the value at a method in BaseController or DerivedController, I want both the values need to be updated. But only the individual scope variable gets updated.
Here is a fiddle demonstrating the same example: http://jsfiddle.net/6df6S/1/
How can changes at a level be made to propagate to the immediate child and immediate parent of the current scope.
We can implement this by using
$scope.$watch
Is there any way to do this without using it or any such watchers?
Edit 1:
By using $scope.$watch here is what I meant
$scope.$watch("value", function () {
$scope.$broadcast("childChangeListener"); //Downwards to all children scopes
$scope.$emit("parentChangeListener"); //Upwards to all parent scopes
});
I was looking for ways in which the value would get updated across all scopes without using such a mechanism.
AngularJS controllers are nothing but plain JavaScript objects which are bound to a particular scope. Angular. js controllers are code that controls certain sections containing DOM elements in which they are declared. They encapsulate the behavior via callbacks and glue $scope models with views.
Nested Controllers: AngularJS allows using nested controllers. It means that you have specified a controller in an HTML element which is a child of another HTML element using another controller.
You can't inject controllers into one another.
Scope InheritanceIf we define nested controllers, then the child controller inherits the scope of its parent controller. We assign values to the models in shapeController. We override message in child controller named circleController.
When multiple controllers need access to the same data, a service should be used. You should not rely on scope inheritance, as it restricts how you can write your HTML. E.g., in the future, you made decide that DerivedController should not be a child of BaseController.
Your service should typically provide a public API, and hide the implementation. This makes it easier to refactor the internals.
HTML:
<div ng-controller="BaseController">
<p>Base Controller Value: {{model.getValue()}}</p>
<button ng-click="model.updateValue('Value updated from Base')">Update In Base</button>
<div ng-controller="DerivedController">
<p>Derived Controller Value: {{model.getValue()}}</p>
<button ng-click="model.updateValue('Value updated from Derived')">Update In Derived</button>
</div>
</div>
JavaScript:
app.factory('sharedModel', function () {
// private stuff
var model = {
value: "initial Value"
};
// public API
return {
getValue: function() {
return model.value;
},
updateValue: function(value) {
model.value = value;
}
};
});
function BaseController($scope, sharedModel) {
$scope.model = sharedModel;
}
function DerivedController($scope, sharedModel) {
$scope.model = sharedModel;
}
Fiddle.
Also, I do not recommend using $rootScope for sharing between controllers.
The binding in your fiddle is directly on a property in scope. The inheritance that you need can be achieved by having the data binding on an object in the scope.
http://jsfiddle.net/2Dtyq/
scope.shared = {}
scope.shared.value = "Something"
Instead of just
scope.value= "Something"
What is happening?
While DerivedController is constructed, the scope being passed in prototypically inherits from the scope of BaseController.
DerivedController's scope object still doesn't have its own property called "value". Therefore it still binds to the property that it got from parent's scope.
Now if you click on the Update In Base button, it will reflect in both the bindings.
The moment you click on Update In Derived button, a new property named "value" is created on the DerviedController's scope. Therefore the binding to the parent's value property is broken. Any more clicks on Update In Base doesn't refresh the second data binding.
Putting it in a separate object prevents a new property from being created so the inheritance is still maintained.
You cannot directly refer to the string value in the child controller. Because of prototypal inheritance setting the property value
on child scope (which gets created when you use a child controller) creates that property on the child scope rather than updating the parent scope property.
Your scope is not the model and therefore we should avoid polluting the $scope
variable with lots of properties. Create a model object and create sub properties on it. This object can then be passed along the child controllers\scope.
I modified your jsfiddle to explain the above point.
Also I highly recommend you to go through this wiki page, to understand the nuisances of prototypal inheritance.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With