0

I have a curious case that I can't figure out...

I have a directive on my app like so:

app.directive('cartTotal', function() {
  return {
    template: "<i ui-sref='cart' class='fa fa-shopping-basket'></i><span class='items'>@{{cartQTotal.total}}</span>"
  };
});

When I load the page, this function fires:

if(localStorage.getItem("cart") != null)
    {
        console.log("makeacart");
        var cart = JSON.parse(localStorage.getItem("cart"));
        $scope.cartQTotal.total = 0;
        for(i=0;i<cart.length;i++)
        {
            $scope.cartQTotal.total += cart[i].cartQ;
        }
        $('.fixed-cart').animateCss('bounce');
    }

This works.

But if I modify $scope.cartQTotal outside of this, such as in a function (still in the parent controller but derived from an ng-click()) for example:

$scope.add2Cart = function(name){
var cart =  JSON.parse(localStorage.getItem("cart"));
        for(var zz = 0;zz<cart.length;zz++)
    {
        if(cart[zz].item == name)
        {
            console.log("already in cart");
            $('.fixed-cart').animateCss('bounce');
            return;
        }
    }
        cart.push({item:name,cartQ:1});
        localStorage.setItem("cart", JSON.stringify(cart));
        console.log("makeacartii");
        $scope.cartQTotal.total = 0;
        for(i=0;i<cart.length;i++)
        {
            $scope.cartQTotal.total += cart[i].cartQ;
        }
        console.log($scope.cartQTotal.total);//THE NUMBER I WANT
        $('.fixed-cart').animateCss('bounce');
}

On //The Number I Want line I get the proper number, as in the variable is correct but my directive template doesn't update. I don't understand why not.

Please assist.

Edit (from the docs):

Observing directives, such as double-curly expressions {{expression}}, register listeners using the $watch() method. This type of directive needs to be notified whenever the expression changes so that it can update the view.

So I guess the question is how do I notify the directive properly?

EDIT 2:

Looking at it using the nginspector extension, it appears I have two scopes with cartQTotal rather than one, this remains constant whether or not I have the directive.

I am very confused because I have my controller scope and then a duplicate scope with all the same variables but the cartQTotal changes in one scope and not the other. Why would I have a duplicate but unnamed controller scope?

Summer Developer
  • 2,056
  • 7
  • 31
  • 68

3 Answers3

1

This is because your directive and $scope and the controller where data is updating both are different..

So you need to pass your controller data to your directive so that it will get modified. For this purpose you can use $broadcast (but make sure you know about it because in large application its not good practice to use it).

So Try this Controller

 cart.push({item:name,cartQ:1});
        localStorage.setItem("cart", JSON.stringify(cart));
        console.log("makeacartii");
        $scope.cartQTotal.total = 0;
        for(i=0;i<cart.length;i++)
        {
            $scope.cartQTotal.total += cart[i].cartQ;
        }
        console.log($scope.cartQTotal.total);//THE NUMBER I WANT
        $('.fixed-cart').animateCss('bounce');

       $rootScope.$broadcast("cartUpdated",$scope.cartQTotal);

directive

$scope.$on('eventEmitedName', function(event, data) {
    $scope.cartQTotal = data;
  });
Saurabh Agrawal
  • 7,581
  • 2
  • 27
  • 51
1

It was a problem as elucidated here: How do I share $scope data between states in angularjs ui-router?

Basically I didn't realize that my ui-router configuration was creating a seperate instance of my controller. Changing my code as specified in that answer allowed it to work properly, even though I wasn't changing states it still affected the directive's ability to communicate with the proper controller instance.

Community
  • 1
  • 1
Summer Developer
  • 2,056
  • 7
  • 31
  • 68
0

Data you wish to use within your directive that is manipulated outside of the directive should be passed in using bindings. There's a great short read here that shows you how. Personally, I use method 6 the most.

The gist is - you add to your directive's returned object:

    scope: {
        yourVariable: '=', //use =? for optional variables
    }

And then use it in your directive as such:

<span>{{your-variable}}</span>

And bind to it as such:

<my-directive your-variable="myControllerVariable"></my-directive>
Sam Bartlett
  • 78
  • 1
  • 9
  • I don't think that's right, I'm not trying to have the data manipulated in the directive passed back to the parent, I'm trying to have the parent (controller) scope go down to the child, it already does this it just isn't happening in some parts of the code (see above). Also when I do use your `=` for two way binding I get a null value. – Summer Developer Feb 20 '17 at 00:32