user3166537
user3166537

Reputation: 35

Angular JS Factory shared in two controllers does not update value

New to Angular, so forgive me, but I have this as my index.html:

<body>
    <div data-ng-controller="storeList">
        <select ng-model="selectedItem" ng-options="c.CustomerID as c.CustomerName for c in customers"
        ng-change="changeCust(selectedItem)">
            <option value="">Select Store</option>
        </select>
    </div>

    <div data-ng-controller="storeInfo">
        Selected Store is: {{selectedStore}}
    </div>
</body>

and this for my js:

var storeApp = angular.module('storeApp',[])
storeApp.factory('currentCustomer',function($http) {
return {
    customerID :0,
    getCustomers: function () {
        console.log("in get")
        return [{CustomerID:1,CustomerName:'Store 1'},
                {CustomerID:2,CustomerName:'Store 2'},
                {CustomerID:3,CustomerName:'Store 3'}]

                }
    }


});


    storeApp.controller('storeList',function($scope,$http,currentCustomer) {
    $scope.customers = currentCustomer.getCustomers()


    $scope.changeCust = function changeCust(id) {
        console.log("Changing ID from: "+ currentCustomer.customerID)
        currentCustomer.customerID = id
        console.log("ID Is now: " + currentCustomer.customerID)
    }

    });
    storeApp.controller('storeInfo',function($scope,currentCustomer) {
    console.log("Setting up storeInfo")
    $scope.man = 'Rob';
    $scope.selectedStore = currentCustomer.customerID;
});

When I change the select, the currentCustomer.customerID changes but does not update in the storeInfo controller.

What am I missing.

Thanks for your help.

Upvotes: 2

Views: 117

Answers (3)

Yogesh
Yogesh

Reputation: 803

If one still want to use the $scope.selectedStore = currentCustomer.customerID;

here is the another approach.

Inter controller communication in Angularjs can be achieved using the following mechanisms.

  1. Using the $rootScope
  2. By Using one of the mechanism for creating the custom services in Angularjs. These are... a) Factory Method b) Value Method c) Service Method or d) Provide Method.

In this article we will use the factory method for inter controller communication in Angularjs

Please have a look at the post http://yogeshtutorials.blogspot.in/2015/11/inter-controller-communication-in.html

Here is the refactored code

HTML

  <div data-ng-controller="storeList">
        <select ng-model="selectedItem" ng-options="c.CustomerID as c.CustomerName for c in customers"
        ng-change="changeCust(selectedItem)">
            <option value="">Select Store</option>
        </select>
    </div>

    <div data-ng-controller="storeInfo">
        Selected Store is: {{selectedStore}}
    </div>

JS:

var storeApp = angular.module('storeApp',[])
storeApp.factory('currentCustomer',function($rootScope) {
  var currentCustomer =  {};
  currentCustomer.customerID = 0;
  currentCustomer.customerName = '';
      currentCustomer.getCustomers =  function () {
          return [{CustomerID:1,CustomerName:'Store 1'},
                  {CustomerID:2,CustomerName:'Store 2'},
                  {CustomerID:3,CustomerName:'Store 3'}]; 
      };
      currentCustomer.setCurrentCustomer = function (custObject) {
        this.customerID = custObject['CustomerID'];
        this.ustomerName = custObject['CustomerName'];
        this.publishChanges();
      }; 

      currentCustomer.getCustomerID = function(){
        return this.customerID;
      };

      currentCustomer.getCustomerName = function(){
        return this.customerName; 
      };      
      currentCustomer.publishChanges = function() {
              $rootScope.$broadcast('custDataChangeEvent');
      };
    return currentCustomer; 
});  

    storeApp.controller('storeList',function($scope,$http,currentCustomer,$filter) {
      $scope.customers = currentCustomer.getCustomers();
      $scope.changeCust = function changeCust(id) {
          var filteredCustomerList = $filter('filter')($scope.customers,{CustomerID:id},true);
          var currCustomer = filteredCustomerList[0];
          currentCustomer.setCurrentCustomer(currCustomer);
      };

    });
      storeApp.controller('storeInfo',function($scope,currentCustomer) {
      // listen to the events
      $scope.$on('custDataChangeEvent',function(){
       $scope.selectedStore = currentCustomer.getCustomerID();
      });
});

Upvotes: 0

Chandan
Chandan

Reputation: 1138

The two binding does not work with primitive data types as there is no reference to bind them and listen changes on them. You can assign the currentCustomer object to the selectedStore scope variable and this way you can listen to changes in both the controllers.

I have done some minor refactoring to Factory instance for better readability and understanding -

var storeApp = angular.module('storeApp',[]);
storeApp.factory('currentCustomer',function() {
    var customerId = 0;

    function getCustomerId()
    {
        return customerId;
    }

    function setCustomerId(id)
    {
        customerId = id;
    }

    return {
        getCustomerId : getCustomerId,
        setCustomerId : setCustomerId,
        getCustomers: function () {
            console.log("in get")
            return [{CustomerID:1,CustomerName:'Store 1'},
                {CustomerID:2,CustomerName:'Store 2'},
                {CustomerID:3,CustomerName:'Store 3'}]

        }
    }


});


storeApp.controller('storeList',function($scope,$http,currentCustomer) {
    $scope.customers = currentCustomer.getCustomers();


    $scope.changeCust = function changeCust(id) {
        console.log("Changing ID from: "+ currentCustomer.getCustomerId())
        currentCustomer.setCustomerId(id);
        console.log("ID Is now: " + currentCustomer.getCustomerId())
    }

});
storeApp.controller('storeInfo',function($scope,currentCustomer) {
    console.log("Setting up storeInfo");
    $scope.man = 'Rob';
    $scope.selectedStore = currentCustomer;
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body ng-app="storeApp">
<div data-ng-controller="storeList">
    <select ng-model="selectedItem" ng-options="c.CustomerID as c.CustomerName for c in customers"
            ng-change="changeCust(selectedItem)">
        <option value="">Select Store</option>
    </select>
</div>

<div data-ng-controller="storeInfo">
    Selected Store is: {{selectedStore.getCustomerId()}}
</div>
</body>

Upvotes: 0

dfsq
dfsq

Reputation: 193261

It's not going to update because when you do

$scope.selectedStore = currentCustomer.customerID;

you create new property selectedStore with value equal to currentCustomer.customerID, but there is no connection (no reference) between them. When original changes it will not reflect in the second.

The simple solution is to use object references:

$scope.selectedStore = currentCustomer;

and use {{selectedStore.customerID}} afterwards.

Upvotes: 2

Related Questions