I have the below code:
HTML
<div id="header">
<h1>The JSON Store</h1>
<div class="cart-info" ng-controller="CartController" quantity="basketContents">
My Cart (<span class="cart-items">{{basketCount()}}</span> items)
</div>
</div>
<div id="main" ng-view></div>
JavaScript
app.controller(
'CartController',
function ($scope, basketService) {
$scope.basketCount = basketService.getCount;
$scope.basketContents = basketService.items;
}
);
app.factory('basketService', function () {
return {
getCount: function () {
var basket = JSON.parse((localStorage.getItem('shoppingBasket') || '{ "items": [] }'));
var count = 0;
basket.items.forEach(function (element) {
count += element.quantity;
});
return count;
},
get items() {
var basket = JSON.parse((localStorage.getItem('shoppingBasket') || '{ "items": [] }'));
var quantities = basket.items.map(function (x) { return x.quantity; });
if (quantities.length > 0) {
var total = quantities.reduce(function (previousValue, currentValue) { return previousValue + currentValue; });
return total;
} else {
return 0;
}
},
addItem: function (item) {
var basket = JSON.parse((localStorage.getItem('shoppingBasket') || '{ "items": [] }'));
var itemStoredAlready = basket.items.filter(function (x) { return x.id === item.id; }).length === 1;
if (itemStoredAlready) {
var basketItem = basket.items.filter(function (x) { return x.id === item.id; })[0];
basketItem.quantity += parseInt(item.quantity, 10);
} else {
var basketItem = {};
basketItem.id = item.id;
basketItem.title = item.title;
basketItem.quantity = parseInt(item.quantity, 10);
basket.items.push(basketItem);
}
localStorage.setItem('shoppingBasket', JSON.stringify(basket));
}
};
});
app.directive('quantity', function () {
var linker = function (scope, element, attrs, basketService) {
scope.$watch(attrs.quantity, function (value, oldValue) {
if (value > oldValue) {
alert("added");
}
}, true);
};
return {
restrict: 'A',
link: linker
};
});
I then have other controllers that handle templates for the "main" div. In one of those controllers it calls basketService.addItem and the view is updated by basketCount() (I don't fully understand how that happens, something is triggering that I assume)
When the addItem is called I would like to do some jQuery animate or fadeIn and I know I have to use a Directive but I cannot understand how I get the directive to watch the addItem function and then to do some jQuery stuff. As you can see I have tried to expose a property in the basketService which is set in the CartController Scope and the custom HTML element but when something is added the HTML element is not getting updated and the directive function is not getting called.
Thanks for your help
Here's a Plunker - http://plnkr.co/edit/gis0114bTRRJLHCdYnMG?p=preview
The animation should be inside a directive (like you said).
And the controller should bind the directive to a property, that changes when the count is changed in the service. You accomplish that when using an isolated scope in the directive.
Here is an example, you can change the css() with your jQuery logic : http://plnkr.co/edit/Mi5QzViUgl5mS21EAKh6?p=preview
Hope it helps,
Shai
I cannot understand how I get the directive to watch the addItem function and then to do some jQuery stuff
Normally, you'll want to $watch a scope property, not a function. Here's one way to do it, that I think simplifies things:
<div class="..." ng-controller="..." quantity> is sufficientThere are other ways, like @ShaiRez suggested -- using an isolated scope. That's more complicated because you need to understand how isolate scopes work and you need to use attributes to pass information into the isolate scope, but it does make your directive more reusable.
Some other observations: