In many scenarios, the data needs to be shared between different scopes. There are different ways to share the data among the scopes. The proper one can be chosen based on the need.
1. Sharing data between Parent scope and Child scope
If Parent-Child relationship can be established, then the data sharing can be implemented as follows.
In AngularJS, Scopes inherits prototypically. ie. In simple terms, if the property is not defined in the child scope, it will be accessed from the parent’s scope. The parent scope’s member variable can be accessed by “$scope.$parent” property from child’s scope.
Javascript
function Parent($scope) {
$scope.x= 5;
$scope.y= 5;
}
function Child($scope) {
$scope.modifyBothScopes= function() {
$scope.$parent.x++;
};
$scope.modifyonlyChildscope= function() {
// member "y" will be created in the child scope
// So, after the following statment, $scope.$parent.y++ will only increment the parent scope.
// It would not affect the child scope.
$scope.y++;
};
}
Html
<div ng-controller="Parent">
parentX = {{x}} <br/>
parentY = {{y}}<br/>
<div ng-controller="Child">
childX = {{x}}<br/>
childY = {{y}}<br/>
<a ng-click="modifyBothScopes()">modifyBothScopes</a><br>
<a ng-click="modifyonlyChildscope()">modifyonlyChildscope</a>
</div>
</div>
JS Fiddle
http://jsfiddle.net/ramandv/JHwxP/
2. Sharing data using Service [like a global variable]
To share the data among independent controllers, Services can be used. Create a service with the data model that needs to be shared. Inject the service in the respective controllers.
In the following example, Service is used to store the variable x. The independent controllers will check the value of X whenever needed.
Javascript
angular.module('myApp', [])
.service('myService', function () {
var x=5 ;
return {
increase : function() {
x++;
},
getX : function() {
return x;
}
};
})
function ControllerA($scope, myService) {
$scope.x = 1;
$scope.incrementDataInService= function() {
myService.increase();
}
$scope.syncDataWithService= function() {
$scope.x = myService.getX();
}
}
function ControllerB($scope, myService) {
$scope.x = 1;
$scope.incrementDataInService= function() {
myService.increase();
}
$scope.syncDataWithService= function() {
$scope.x = myService.getX();
}
}
HTML
<div ng-app="myApp">
<div ng-controller="ControllerA">
ControllerA.X = {{x}}<br/>
<a ng-click="incrementDataInService()">incrementDataInService</a><br>
<a ng-click="syncDataWithService()">syncDataWithService</a><br>
</div>
<hr/>
<div ng-controller="ControllerB">
ControllerB.X = {{x}}<br/>
<a ng-click="incrementDataInService()">incrementDataInService</a><br>
<a ng-click="syncDataWithService()">syncDataWithService</a><br>
</div>
</div>
JS Fiddle
http://jsfiddle.net/ramandv/kR859/
3. Sharing data using Service – monitor the changes
In some times, it is important to monitor the changes in the service. AngularJS provides “$broadcast” to broadcast the data to the listening subscribers.
The following contrived example shows the usage of $broadcast. The ControllerA and ControllerB subscribed to the event “XChanged”. The service “myService” will broadcast the event “XChanged” when the value of “x” changes.
Javascript
angular.module('myApp', [])
.service('myService', function ($rootScope) {
var x=5 ;
return {
increase : function() {
x++;
$rootScope.$broadcast('XChanged', x);
}
};
})
function ControllerA($scope, myService) {
$scope.x = 1;
$scope.incrementDataInService= function() {
myService.increase();
}
$scope.$on('XChanged', function(event, x) {
$scope.x = x;
});
}
function ControllerB($scope, myService) {
$scope.x = 1;
$scope.incrementDataInService= function() {
myService.increase();
}
$scope.$on('XChanged', function(event, x) {
$scope.x = x;
});
}
HTML
<div ng-app="myApp">
<div ng-controller="ControllerA">
ControllerA.X = {{x}}<br/>
<a ng-click="incrementDataInService()">incrementDataInService</a><br>
</div>
<hr/>
<div ng-controller="ControllerB">
ControllerB.X = {{x}}<br/>
<a ng-click="incrementDataInService()">incrementDataInService</a><br>
</div>
</div>
JS Fiddle
Great examples. Just what I needed. Thank you!
Answers so many questions I haven’t had answer for TYTY!
I think there is a fourth way, which is to make ‘x’ an object so you can monitor changes without the need for broadcasting.
http://jsfiddle.net/RphNp/1/
Broadcast is mainly for example. I personally tried to avoid to broadcast, as the code clarity will be spoiled.
Your example seems to me like the method 2 . Correct me If I am wrong?
agree on avoiding the broadcast
for 3) if we have functions other than increasse, like multiply, decrease – we will need broadcast in each of them
also not sure is there overhead in broadcast a “big object”, i.e. whether it is better to broadcast the event, then getX(), (push+pull) or broadcast the obj the direct (pure push)
finally i found best for my case to use watch on scope variable
referring service property http://stackoverflow.com/questions/12576798/angularjs-how-to-watch-service-variables
I was searching for this solution for 2 days. Was starting to despair and thinking the switch to Angular was going to cost me my job. Thanks soooo much for this excellent tutorial!
Oh btw, I fixed your fiddle. The angular library link was broken. Changed it to http://code.angularjs.org/1.1.0/angular.min.js
http://jsfiddle.net/25CVc/19/
Pingback: angularjs sharing data | ynfiesta
Perfect tutorial. Simple and to the point. I look forward to reading more.
You should have also leave a example making the parent scope element as an object, so that it can be changed in child controller directly (Magic of ‘.’). still very useful.
function Parent($scope) {
$scope.x= {z:5};
$scope.y= 5;
}
function Child($scope) {
$scope.modifyBothScopes= function() {
$scope.x.f++;
};
$scope.modifyonlyChildscope= function() {
// member "y" will be created in the child scope
// So, after the following statment, $scope.$parent.y++ will only increment the parent scope. It would not affect the child scope.
$scope.y++;
};
}
What happens to the data stored in the service if the user refreshes the page in the browser?
Does it get cleared?
Yes. It will get cleared. If data needs to be persistent, store it in local storage.
So, I know I’m late to the game, but I’m not sure all the JSFiddle links work anymore 🙁 I could be doing it wrong (never put it past me), but I’d just throw it out there.
Hey Austin,
Thanks for letting me know. Fixed it.
Very useful, thank you very much!
Pingback: The Top 10 Mistakes AngularJS Developers Make | Cipto's Blog