Hervé Guétin
Hervé Guétin

Reputation: 4392

Controllers not talking to each other via service in Angular JS

I am trying to send data from one controller to another with no success. I have tried all ideas found on Stack Overflow using Angular services and I can't see what's wrong with my code.

I have a first controller that lists some items (CartSidebarCtrl). It also has the ability to remove items from the list.

I have another controller that should display the number of items (TopCartCtrl).

On page load, the second controller displays the correct number of items. But when I remove some items in the first controller, the second is not updated.

What am I doing wrong here ?

HTML Code:

<div ng-controller="CartSidebarCtrl">
    <ul>
        <li ng-repeat="product in products">
            {{product.name}} (<span style="color: blue; cursor: pointer" ng-click="remove($index)">Remove</span>)
        </li>
    </ul>
</div>

<div ng-controller="TopCartCtrl">
    <span>{{topCartText}}</span>
</div>

Angular Code:

magentoApp.factory('cartModel', function () {
    var cartModel = {};

    cartModel.updateProducts = function(products) {
        cartModel.products = products;
    };

    return cartModel;
});

magentoApp.controller('CartSidebarCtrl', ['$scope', '$http', 'cartModel', function($scope, $http, cartModel) {
    $scope.products = [
        { name: 'Product 1' },
        { name: 'Product 2' }
    ];

    $scope.remove = function($index) {
        $scope.products.splice($index, 1);
        updateTopCart();
    }

    updateTopCart = function() {
        cartModel.updateProducts($scope.products);
    }

    updateTopCart();
}]);

magentoApp.controller('TopCartCtrl', ['$scope', 'cartModel', function($scope, cartModel) {
    $scope.topCartText = cartModel.products.length;
}]);

[EDIT WITH UPDATED CODE WORKING]

Beside the fact that object reference was not correct as mentionned by 'm59' and 'Jesus Rodriguez', I was calling for .length on cartModel.products. For the same reason, my template was not updated. My solution is then to pass the products object to the template and call .length on this template. Then, I wanted to display a different text based on products.length and made this work by creating a custom filter.

Here is the correct code.

HTML:

<div ng-controller="TopCartCtrl">
    <span>{{products.length | topCartFilter}}</span>
</div>

<div ng-controller="CartSidebarCtrl">
    <ul>
        <li ng-repeat="product in products">
            {{product.name}} (<span style="color: blue; cursor: pointer" ng-click="remove($index)">Remove</span>)
        </li>
    </ul>
</div>

Angular:

magentoApp.factory('cartModel', function() {
    var cartModel = {
        products: [
            { name: 'Product 1' },
            { name: 'Product 2' }
        ]
    };
    return cartModel;
});

magentoApp.filter('topCartFilter', function() {
    return function(productsCount) {
        return (productsCount > 0) ? 'You have ' + productsCount + ' items in your cart': 'Your cart is empty';
    };
});

magentoApp.controller('TopCartCtrl', ['$scope', 'cartModel', function($scope, cartModel) {
    $scope.products = cartModel.products;
}]);

magentoApp.controller('CartSidebarCtrl', ['$scope', 'cartModel', function($scope, cartModel) {
    $scope.products = cartModel.products;

    $scope.remove = function($index) {
        $scope.products.splice($index, 1);
    }
}]);

Upvotes: 1

Views: 791

Answers (1)

m59
m59

Reputation: 43745

I just remembered I already answered this here: How to share data between controllers in angularjs

var app = angular.module('myApp', []);

app.factory('myService', function() {
  var myService = {
    foo: 'bar'
  };
  return myService;
});

app.controller('myCtrl1', function(myService) {
  console.log(myService.foo);
  myService.foo = 'not bar anymore!';
});

app.controller('myCtrl2', function(myService) {
  console.log(myService.foo);
});

The only thing you need to do is then set your $scope.cartModel = cartModel and then you could do things like ng-model="cartModel.someProp" and any change there is updating that property in your service and thus updating it to any $scope.cartModel that is referencing the service object.

Upvotes: 1

Related Questions