Passing data between controllers in Angular JS?

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

  • {{product.name}}
  • //click one added here
  • //click two added here
  • 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.

    Solutions/Answers:

    Solution 1:

    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();
    });
    

    Solution 2:

    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 3:

    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>
    

    Solution 4:

    You can do this by two methods.

    1. 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.

    2. 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.

    Solution 5:

    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.

    Solution 6:

    angular.module('testAppControllers', [])
        .controller('ctrlOne', function ($scope) {
            $scope.$broadcast('test');
        })
        .controller('ctrlTwo', function ($scope) {
            $scope.$on('test', function() {
            });
        });
    

    Related:  Can you use hash navigation without affecting history?