Passing data between controllers in Angular JS?
I have a basic controller that displays my products,
App.controller('ProductCtrl',function($scope,$productFactory){
$productFactory.get().success(function(data){
$scope.products = data;
});
});
In my view I'm displaying this products in a list
<ul>
<li ng-repeat="product as products">
{{product.name}}
</li>
</ul
What I'm trying to do is when someone click on the product name, i have another view named cart where this product is added.
<ul class="cart">
<li>
//click one added here
</li>
<li>
//click two added here
</li>
</ul>
So my doubt here is, how do pass this clicked products from first controller to second? i assumed that cart should be a controller too.
I handle click event using directive. Also i feel i should be using service to achieve above functionality just can't figure how? because cart will be predefined number of products added could be 5/10 depending on which page user is. So i would like to keep this generic.
Update:
I created a service to broadcast and in the second controller i receive it. Now the query is how do i update dom? Since my list to drop product is pretty hardcoded.
From the description, seems as though you should be using a service. Check out http://egghead.io/lessons/angularjs-sharing-data-between-controllers and AngularJS Service Passing Data Between Controllers to see some examples.
You could define your product service (as a factory) as such:
app.factory('productService', function() {
var productList = [];
var addProduct = function(newObj) {
productList.push(newObj);
};
var getProducts = function(){
return productList;
};
return {
addProduct: addProduct,
getProducts: getProducts
};
});
Dependency inject the service into both controllers.
In your ProductController
, define some action that adds the selected object to the array:
app.controller('ProductController', function($scope, productService) {
$scope.callToAddToProductList = function(currObj){
productService.addProduct(currObj);
};
});
In your CartController
, get the products from the service:
app.controller('CartController', function($scope, productService) {
$scope.products = productService.getProducts();
});
how do pass this clicked products from first controller to second?
On click you can call method that invokes broadcast:
$rootScope.$broadcast('SOME_TAG', 'your value');
and the second controller will listen on this tag like:
$scope.$on('SOME_TAG', function(response) {
// ....
})
Since we can't inject $scope into services, there is nothing like a singleton $scope.
But we can inject $rootScope
. So if you store value into the Service, you can run $rootScope.$broadcast('SOME_TAG', 'your value');
in the Service body. (See @Charx description about services)
app.service('productService', function($rootScope) {/*....*/}
Please check good article about $broadcast, $emit
Solution without creating Service, using $rootScope:
To share properties across app Controllers you can use Angular $rootScope. This is another option to share data, putting it so that people know about it.
The preferred way to share some functionality across Controllers is Services, to read or change a global property you can use $rootscope.
var app = angular.module('mymodule',[]);
app.controller('Ctrl1', ['$scope','$rootScope',
function($scope, $rootScope) {
$rootScope.showBanner = true;
}]);
app.controller('Ctrl2', ['$scope','$rootScope',
function($scope, $rootScope) {
$rootScope.showBanner = false;
}]);
Using $rootScope in a template (Access properties with $root):
<div ng-controller="Ctrl1">
<div class="banner" ng-show="$root.showBanner"> </div>
</div>
You can do this by two methods.
By using
$rootscope
, but I don't reccommend this. The$rootScope
is the top-most scope. An app can have only one$rootScope
which will be shared among all the components of an app. Hence it acts like a global variable.-
Using services. You can do this by sharing a service between two controllers. Code for service may look like this:
app.service('shareDataService', function() { var myList = []; var addList = function(newObj) { myList.push(newObj); } var getList = function(){ return myList; } return { addList: addList, getList: getList }; });
You can see my fiddle here.
An even simpler way to share the data between controllers is using nested data structures. Instead of, for example
$scope.customer = {};
we can use
$scope.data = { customer: {} };
The data
property will be inherited from parent scope so we can overwrite its fields, keeping the access from other controllers.