AngularJS directive not updating - javascript

I have a directive that seems to set everything properly when Angular instantiates the page, but doesn't update when I interact with its components.
HTML :
<div class="app-table col-md-6 col-sm-12 col-xs-12" app-table>
<header>
<span class="col-xs-12">Subscriptions</span>
</header>
<div class="pagination">
<span class="user-controls">
<span class="page-down glyphicon glyphicon-chevron-left"></span>
<input type="text" ng-model="page"/>
<span>/ {{summary.subscriptions.pages}}</span>
<span class="page-up glyphicon glyphicon-chevron-right"></span>
</span>
<span class="results-text">Results 1 - {{summary.subscriptions.labels.length}} of {{summary.subscriptions.total}}</span>
</div>
<table class="col-xs-12 table-striped">
<thead>
<td class="col-xs-9">Name</td>
<td class="col-xs-3">Subscribers</td>
</thead>
<tbody>
<tr ng-repeat="label in summary.subscriptions.labels | limitTo: 5 : offset">
<td class="col-xs-9">{{label.name}}</td>
<td class="col-xs-3">{{label.subscribers}}</td>
</tr>
</tbody>
</table>
</div>
Controller:
app.controller('DashboardCtrl', ['$scope', 'DashboardService', function($scope, DashboardService) {
$scope.summary = {};
$scope.init = function() {
DashboardService.getSummary().then(function(response){
$scope.summary = response;
});
};
$scope.init();
}]);
Directive:
app.directive('appTable', [function () {
return {
restrict: 'A',
scope: true,
link: function (scope, elem) {
scope.offset = 0;
scope.page = 1;
elem.find('.page-up').bind('click', function(){
scope.offset += 5;
scope.page += 1;
});
elem.find('.page-down').bind('click', function(){
scope.offset -= 5;
scope.page -= 1;
});
}
};
}]);
When the page loads it correctly shows page 1 with an offset of 0. If I change the variable to page=2 and offset=5 then the page loads as would be expected, the values are populated correctly, and the offset correctly shows the subscriptions for indexes 6-10. However, when I click the buttons that the click elements are bound to I don't see the page or offset variables update, even though I can verify through the Chrome Dev Tools that the click bindings are being hit. It seems the directive is not passing the scope variables to the parent controller properly?

This is still issue about using jquery in angularjs.
In fact offset and page are already changed in your scope, but if you want to reflect them on your view, you have to call scope.$apply() to let angular rerender your page.
var app = angular.module("app", []);
app.controller('DashboardCtrl', ['$scope', function($scope) {
$scope.summary = {
subscriptions: {
labels: [
{
name: 'name1',
subscribers: 'A,B'
},{
name: 'name2',
subscribers: 'A,B,C'
},{
name: 'name3',
subscribers: 'A,B,C,D'
}
],
total: 10,
pages: 1
}
};
//$scope.offset = 0;
//$scope.page = 1;
}]);
app.directive('appTable', [function() {
return {
restrict: 'A',
scope: true,
link: function(scope, elem) {
scope.offset = 0;
scope.page = 1;
elem.find('.page-up').on('click', function() {
scope.$apply(function() {
scope.offset += 5;
scope.page += 1;
});
});
elem.find('.page-down').on('click', function() {
scope.$apply(function() {
scope.offset -= 5;
scope.page -= 1;
});
});
}
};
}]);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
<div ng-app="app" ng-controller="DashboardCtrl">
<div class="app-table col-md-6 col-sm-12 col-xs-12" app-table>
<header>
<span class="col-xs-12">Subscriptions</span>
</header>
<div class="pagination">
<span class="user-controls">
<span class="page-down glyphicon glyphicon-chevron-left">PageDown</span><br>
<input type="text" ng-model="page" />
<span>/ {{summary.subscriptions.pages}}</span><br>
<span class="page-up glyphicon glyphicon-chevron-right">PageUp</span><br>
</span>
<span class="results-text">Results 1 - {{summary.subscriptions.labels.length}} of {{summary.subscriptions.total}}</span>
</div>
<table class="col-xs-12 table-striped">
<thead>
<td class="col-xs-9">Name</td>
<td class="col-xs-3">Subscribers</td>
</thead>
<tbody>
<tr ng-repeat="label in summary.subscriptions.labels | limitTo: 5 : offset">
<td class="col-xs-9">{{label.name}}</td>
<td class="col-xs-3">{{label.subscribers}}</td>
</tr>
</tbody>
</table>
{{offset}}
{{page}}
</div>

I think you have 2 separate issues.
The first issue is that you are calling a click handler outside of Angular, so it doesn't know it needs to run its digest cycle. You can solve this by attaching ng-click on your page-up and page-down elements, or by calling $apply:
elem.find('.page-up').bind('click', function(){
scope.$apply(function () {
scope.offset += 5;
scope.page += 1;
});
});
The second issue is that your directive has scope: true which means it is inherting the parent (controller) scope via prototypal inheritance. So when your directive starts to set page and offset onto the scope, it creates new variables on its own scope, which any outer scope like the controller doesn't see:
link: function (scope, elem) {
// Creating new variables on the child scope
scope.offset = 0;
scope.page = 1;
elem.find('.page-up').bind('click', function(){
// Updating variables on the child scope
scope.offset += 5;
scope.page += 1;
});
}
So if you add {{ page }} and {{ offset }} markup inside the app-table element, you'll see it update. But if you add that markup outside of the app-table element (but still inside your ng-controller element) you will see that the controller does not have the new information.
It should work if you set scope: false, because then you'd be writing to the same exact scope as the controller.
It can work with scope: true if you use objects in your controller instead:
scope.pagination = {
offset: 0;
page: 1
};
Also, I'm not sure if the example presented here is simplified, but you are basically using an Angular directive to do jQuery. Have you considered making an independent pagination component, with scope: "=" (isolate scope)? Then you could explicitly pass in the data it needs (page, offset, total, .etc), and the directive could have its own template.

Related

ngClass doesn't apply changes in parent directive

i made two directives, one's exposing an API for another directive using controller.
The child directive is a 'bodyElement' directive, and when clicked should update a class of the parent directive template.
While the modification of the parent $scope applies, the ngClass switch doesn't apply.
Hope you can help:
Directives:
.directive('humanBody', function () {
return {
transclude : true,
scope: {},
templateUrl: 'view1/template/human-body.tpl.html',
controller: ['$scope', function ($scope) {
$scope.form = {};
$scope.body = {};
$scope.body.selection = {};
$scope.body.selection.head = true;
$scope.body.selection.arm = false;
$scope.body.selection.chest = false;
$scope.body.selection.leg = false;
$scope.isActive = function (type) {
return $scope.body.selection[type];
};
this.toggle = function (type) {
$scope.body.selection[type] = !$scope.body.selection[type];
}
}]
}
})
.directive('bodyPart', function () {
return {
transclude : true,
scope: {
type: '#'
},
require: '^humanBody',
link: function (scope, elem, attr, humanBody) {
elem.on('click', function (event) {
console.info('toggle ' + scope.type);
humanBody.toggle(scope.type);
});
}
}
});
template of parent directive:
i need that isActive(type) in ngClass switch between no-background <-> type-container when toggling (false/true).
It just work when rendering the page.
<div class="container">
<div class="row col-xs-12 body-part-container body-container">
<div class="col-xs-12 "
ng-class="{'no-background': !isActive('head'), 'head-container':isActive('head')}">
<div class=" col-xs-12 arm-container"
ng-class="{'no-background': !isActive('arm'), 'arm-container':isActive('arm')}">
<div class="col-xs-12 chest-container"
ng-class="{'no-background': !isActive('chest'), 'chest-container':isActive('chest')}">
<div class="col-xs-12 leg-container container"
ng-class="{'no-background': !isActive('leg'), 'leg-container':isActive('leg')}">
<body-part type="head" class="head col-xs-12"></body-part>
<body-part type="arm" class="arm col-xs-4"></body-part>
<body-part type="chest" class="chest col-xs-4"></body-part>
<body-part type="arm" class="arm col-xs-4"></body-part>
<body-part type="leg" class="leg col-xs-12"></body-part>
</div>
</div>
</div>
</div>
</div>
</div>
You need to kick off digest cycle in bodyPart directive, as you are updating scope variable from customEvent(updating angular context from outside world wouldn't intimate angular to run digest cycle to update view level bindings).
Code
elem.on('click', function (event) {
console.info('toggle ' + scope.type);
humanBody.toggle(scope.type);
scope.$apply();
});

AngularJs doesn't update the model when the input data is changed

I have angular application which uses directives.
In the directive I have template that defines pop up modal.
Basically, it's very simple app that shows a list of book authors, and in the list there is an Edit button that opens modal box.
If I open the modal for editing the book author, and just close it, without editing the author - there is no problem.
But if I open the modal, and type something in the author input, and close it, the model is stuck with the current input value for the whole time, so if I open another author for editing, the model will not be updated.
My question is: why is this happening, and how to fix it ?
HTML
<div ng-controller="MyCtrl">
<table class="table table-hover">
<tr>
<td><b>Publisher</b></td>
<td><b>Edit Publisher</b></td>
</tr>
<tr ng-repeat="book in books">
<td>
{{book.Author}}
</td>
<td>
<span ng-click="toggleModal(book)" class="btn btn-primary">Edit</span>
</td>
</tr>
</table>
<modal-dialog info='modalShown' show='modalShown' width='600px' height='60%'>
<div ng-show="divBook">
<input type="text" name="bookAuthor" ng-model="bookAuthor" />
</div>
</modal-dialog>
</div>
Angular
var myApp = angular.module('myApp',[]);
myApp.controller("MyCtrl", function($scope){
$scope.books = [{Author:"Jon Skeet"},{Author:"John Papa"},{Author:"Scott Hanselman"}];
$scope.modalShown = false;
$scope.toggleModal = function (book) {
$scope.bookAuthor = book.Author;
$scope.modalShown = !$scope.modalShown;
$scope.divBook = true;
};
});
myApp.directive('modalDialog', function () {
return {
restrict: 'E',
template: "<div class='ng-modal' ng-show='show'>"
+"<div class='ng-modal-overlay' ng-click='hideModal()'>"
+"</div>"
+"<div class='ng-modal-dialog' ng-style='dialogStyle'>"
+"<div class='ng-modal-close' ng-click='hideModal()'>X</div>"
+"<div class='ng-modal-dialog-content' ng-transclude>"
+"</div>"
+"</div>"
+"div>",
replace: true,
scope: {
show: '=info'
},
transclude: true,
link: function (scope, element, attrs) {
//scope.apply();
scope.dialogStyle = {};
if (attrs.width)
scope.dialogStyle.width = attrs.width;
if (attrs.height)
scope.dialogStyle.height = attrs.height;
scope.hideModal = function () {
scope.show = false;
};
}
};
});
So, the test case will be:
Click Edit -> change the value -> close the modal
Click Edit on another author.
JSFiddle: http://jsfiddle.net/HB7LU/17694/
The model value is changing, however you are creating a new variable and not modifying the original element of the array.
You can change that by putting a pointer of the array object in a scope variable
$scope.toggleModal = function (book) {
$scope.book = book;
$scope.modalShown = !$scope.modalShown;
$scope.divBook = true;
};
then pointing the ng-model to the .Author property of the object.
<input type="text" name="bookAuthor" ng-model="book.Author" />
See modified JSFiddle: http://jsfiddle.net/9a2jcc9u/1/
I have changed your JS fiddle, if you want to change name and it automatically changes in grid than remove angular.copy(book) and directly assign book. you can see your jsfiddle here jsfiddle
myApp.controller("MyCtrl", function($scope){
$scope.books = [{Author:"Jon Skeet"},{Author:"John Papa"},{Author:"Scott Hanselman"}];
$scope.modalShown = false;
$scope.toggleModal = function (book) {
$scope.book = angular.copy(book);
$scope.modalShown = !$scope.modalShown;
$scope.divBook = true;
};
});
your modal dialog
<modal-dialog info='modalShown' show='modalShown' width='600px' height='60%'>
<div ng-show="divBook">
<input type="text" name="bookAuthor" ng-model="book.Author" />
</div>
</modal-dialog>
try something like this
myApp.controller('MyCtrl', ['$scope',function($scope) {
//your code
}]);

How dynamically add new input element if all others was filled in AngularJS

please watch this Plunker
So I working with angular and need to add new input field when all others are filled in (by default on page placed 5 inputs and if all of them are filled automatically add one more input if new input also using will add one more input and etc).
For generate inputs I use ng-repeat and name_list[] for it:
<div collect-input>
<div class="form-group" ng-repeat="(i, name) in name_list track by $index">
<div class="row">
<div class="col-xs-12">
<input class="form-control" type="text" ng-model="data.name_list[i]" add-input/>
</div>
</div>
</div>
Each input have directive attr "add-input" with $watch() method inside. This method method track when $isEmpty parameter had changed.
Then value function pass value of this parameter to listen function.
directive('addInput', ['$compile', '$sce', '$timeout', function ($compile, $sce, $timeout) {
return {
restrict: 'A',
require: ['^collectInput', '?ngModel'],
link: function (scope, element, attrs, ctrl) {
var collectInput = ctrl[0];
var ngModel = ctrl[1];
$timeout(function(){
scope.$watch(
function(){
return ngModel.$isEmpty(ngModel.$modelValue);
},
function(isEmpty){
collectInput.reportInput(ngModel, isEmpty);
}
);
},1000)
}
}
}]);
Then this function call "reportInput()" that placed inside parent directive "collect-input". Main goal of this function is to add new input name to name_list[] for generating via ng-repeat
userApp.directive('collectInput', function() {
return {
restrict: 'A',
controller: function($scope) {
var dirtyCount = 0;
this.reportInput = function(modelValue, isEmpty) {
var count = $scope.name_list.length;
if (isEmpty == false){
dirtyCount ++;
console.log('+1:' + dirtyCount);
}
if (isEmpty == true){
if (dirtyCount <= 0){
dirtyCount = 0;
console.log('0:' + dirtyCount);
}
else if(dirtyCount > 0){
dirtyCount --;
console.log('-1:' + dirtyCount)
}
}
if (count === dirtyCount) {
$scope.name_list.push(modelValue);
//dirtyCount = dirtyCount + 1;
}
console.log('count:' + count);
console.log('dirtyCount:' + dirtyCount);
console.log(modelValue)
}
},
link: function(scope, element, attrs) {
}}});
So when I filled 5 default inputs everything is good after it appears new input but it is all in my IDE it work perfect if I add only one symbol for 5+ label (in plunker in some reason it not work) but when I add or delete something more code logic crash. It's hard to explain. I hope Plunker code more clarify this.
Not tested, and could be optimized, but here's my idea:
HTML :
<div class="form-group" ng-repeat="name in name_list">
<div class="row">
<div class="col-xs-12">
<input class="form-control" ng-model="name"/>
</div>
</div>
</div>
JS :
//watch any modification in the list of names
$scope.$watchCollection('data.name_list', function (list) {
//is there an empty name in the list?
if (!list.filter(function (name) { return !name; }).length) {
//if not, let's add one.
data.name_list.push('');
//and that will automatically add an input to the html
}
});
I don't see the point of a directive.

I'm having trouble replicating simplest of javascript code using angular directive

I'd written a very simple widget/snippet. Five stars (using font-awesome) on hover, replace empty star with filled star. On mouse out go back to default no. of star if there is a default value, and on-click change the default value depending on the star clicked (for example click on 4th star would change the value to 4 and so on. Really simple stuff. I can't for the life of me replicate it using angular js...
I know I need to do it using directives and transclusion if I understand it correctly. I'm having so much trouble even getting variable no. of filled and empty stars based on default value....
I'd appreciate it if someone could direct me.. here's the code.
Html stuff
<div class="ratingList" rating-widget rate='{{ rating }}' increment="increment()">
<span>Hate it</span>
<span class="star"><i class="fa fa-star-o fa-lg"></i></span>
<span class="star"><i class="fa fa-star-o fa-lg"></i></span>
<span class="star"><i class="fa fa-star-o fa-lg"></i></span>
<span class="star"><i class="fa fa-star-o fa-lg"></i></span>
<span class="star"><i class="fa fa-star-o fa-lg"></i></span>
<span>love it</span>
very basic controller
bmApp.controller('MainController', ['$scope', function($scope){
$scope.rating = 3;
$scope.increment = function(){
$scope.rating = $scope.rating + 1;
}
}]);
culprit directive
bmApp.directive('ratingWidget', function(){
return{
restrict: 'A',
replace:true,
transclude:true,
template: '<div><button ng-click="increment()">Click</button><div class="rating"></div></div>',
controller:['$scope', '$element', '$transclude', function($scope, $element, $transclude){
$transclude(function(clone){
var stars = clone.filter('.star');
var filledStar = $('<span class="star"><i class="fa fa-star fa-lg"></i></span>');
var container = $element.find('.rating');
angular.forEach(stars, function(val, key){
var star = $(val);
if(key<$scope.rate)
{
//console.log(key);
container.append(filledStar);
//star.replaceWith(filledStar);
//angular.element(star.children()[0]).removeClass('fa-star-o').addClass('fa-star')
}else{
//console.log(key);
container.append(star);
}
});
});
}],
scope:{
rate:'#',
increment:'&'
}
}
});
I'm stuck at the very begining, can't show filled stars based on default value... The append is resulting in 3 stars...
There are a few different ways of being able to handle this sort of functionality.
I've updated your example to show the use of the isolate scope and transclusion (for the increment() button).
We also bundle the star markup into the ratingWidget directive to make it modular and keep it as more of a standalone component.
You can see that because of the ng-repeat and ng-class directives we don't have to work directly with HTML elements if we don't want to, Angular handles the heavy lifting through data binding.
Here is a plunker: http://plnkr.co/edit/hd5DLOpRC3R9EFy316Gl?p=preview
(If you look at the history on that Plunker you will see how I was using jQuery to manipulate the elements/classes directly)
HTML:
<div ng-app="bmApp">
<div ng-controller="MainController">
<div rating-widget rate="rating" max-rating="maxRating">
<!--
This is the content that will be transcluded.
Transclusion means that this content will linked with
the parent scope instead of being linked into the
scope of the `ratingWidget`.
i.e. the `increment()` function is defined in `MainController`
not in the `ratingWidget`.
-->
<button ng-click="increment()">Click</button>
</div>
</div>
</div>
JavaScript:
var bmApp = angular.module('bmApp', []);
bmApp.controller('MainController', ['$scope',
function($scope) {
$scope.rating = 3;
$scope.maxRating = 6;
$scope.increment = function() {
if ($scope.rating < $scope.maxRating){
$scope.rating += 1;
}
}
}]);
bmApp.directive('ratingWidget', function() {
return {
restrict: 'A',
transclude: true,
scope: {
rate: '=',
maxRating: '='
},
link: function(scope, element, attr){
var classes = {
empty: 'fa-star-o',
full: 'fa-star'
};
scope.stars = [];
scope.$watch('maxRating', function(maxRating){
maxRating = maxRating || 5;
scope.stars.length = maxRating;
for (var i = 0, len = scope.stars.length; i < len; i++){
if (!scope.stars[i]){
scope.stars[i] = {
cssClass: classes.empty
};
}
}
updateRating(scope.rate);
});
scope.$watch('rate', function(newRating){
updateRating(newRating);
});
scope.selectRating = function(index){
// The $index is zero-index but the ratings
// start at one, so add 1.
scope.rate = index + 1;
}
function updateRating(rating){
rating = rating || 0;
for (var i = 0, len = scope.stars.length; i < len; i++){
var star = scope.stars[i];
if (i < rating){
star.cssClass = classes.full;
} else {
star.cssClass = classes.empty;
}
}
}
},
template: '<div>' +
'<div class="ratingList">' +
'<span>Hate it</span>' +
'<span class="stars">' +
'<span class="star" ng-click="selectRating($index)" ng-repeat="star in stars track by $index"><i class="fa fa-lg" ng-class="star.cssClass"></i></span>' +
'</span>' +
'<span>love it</span>' +
'</div>' +
'<div ng-transclude></div' +
'</div>'
}
})
Edit:
#dan-tang
Yes, if you had the button outside the directive but inside MainController it would all work as expected and you wouldn't need transclude.
But the point is that the button is inside the directive and calling a method defined on MainController. To do that we need to transclude the content so that binds to the parent scope.
Here's a plunker showing this example: http://plnkr.co/edit/x9xZwve9VkwbTGKUGjZJ?p=preview
HTML:
<div ng-controller="MainCtrl">
<div>I am: {{name}}</div>
<div widget>
<!--
Without transclusion this will say 'widget', with transclusion this will say 'controller'.
Transclusion lets us control the scope to which these expressions are bound.
-->
<div>I am: {{name}}</div>
</div>
</div>
JavaScript:
testApp.controller('MainCtrl', ['$scope', function($scope){
$scope.name = 'controller';
}]);
testApp.directive('widget', function(){
return {
scope: true,
transclude: true,
link: function(scope, element, attr){
scope.name = 'widget'
},
template: '<div>' +
'<div>I am: {{name}}</div>' +
'<div ng-transclude></div>' +
'</div>'
}
});
I would say that transclude in Angular is like a closure in JavaScript - it lets you control the scope to which variables and expressions are bound.
Here's a rough JavaScript analogue of the example above to show some of the similarities between the two concepts:
var name = 'controller';
var printCallback = function(){
console.log('name=' + name);
}
function Widget(printCallback){
var name = 'widget';
this.printName = function(){
console.log('name=' + name);
printCallback();
}
}
var widget = new Widget(printCallback);
widget.printName();
// Prints:
// name=widget
// name=controller
A ratings system customize level and easy installation , the best I found: https://rating-widget.com/get/rating/

AngularJs : how to do a $watch on a function to evoid the error: $digest() iterations reached

I have a list with items. Each item of a list can be selected. If I select the item, it will be pushed in the cookies.
In my home.html (here I have the list with the items that I can add to cookies)
<table class="table" >
<tr data-ng-repeat="item in items">
<td><span >{{item.title}}</span></td>
<td> <button data-ng-click="addToCookies(item)" data-ng-disabled="item.added" class="btn">
<span data-ng-show="!item[$index].added" class="text-center">Add To cookies</span>
<span data-ng-show="item[$index].added" class="text-center">Added To cookies</span>
</button>
</td>
</tr>
<tr></tr>
</table>
In page cookies.html I call the getCookiesItem() and the directive :
<div class="navbar navbar-right" data-ng-controller="ctrlItemsList">
<div data-item-list data-items="getCookiesItem()" ></div>
</div>
In my controller I did :
//TO ADD ELEMENT SELECTED IN THE COOKIE
$scope.addToCookies = function (item){
item.added=true;
angular.extend($scope.criteria, item);
cookiesItems.addItem($scope.criteria);
}
//TO GET ELEMENTS COOKIE (MAYBE I HAVE TO DO A $WATCH OF THIS FUNCTION)
$scope.getCookiesItem = function (){
return cookiesItems.getItems();
}
In my service I have :
Cservices.factory('cookiesItems', ['$cookieStore', function($cookieStore) {
var items = [];
return {
addItem: function( itemSelected){
var array = [];
if ($cookieStore.get('key') === undefined) {
$cookieStore.put('key', []);
}else{
array = $cookieStore.get('key');
}
array.push(itemSelected);
$cookieStore.put('key', array);
},
removeItem: function(itemSelected){
var array = $cookieStore.get('key');
if(array != undefined){
for (var i = 0; i < array.length; ) {
if (array[i].id=== itemSelected.id) {
array.splice(array[i], 1);
} else {
++i;
}
}
}
$cookieStore.put('key', array);
},
getItems: function(){
return $cookieStore.get('key');
}
The elements cookies are print in the following directive:
template :
<table class="table" >
<tr data-ng-repeat="item in items">
<td>{{item.title}}</td>
</tr>
<tr></tr>
</table>
in the js :
iDirective.directive('itemList', function() {
return {
restrict: 'A',
transclude: true,
scope: {
items: '=items'
}
templateUrl: ''
};
});
I have the following error:
Error: [$rootScope:infdig] 10 $digest() iterations reached. Aborting!
Watchers fired in the last 5 iterations: [["fn: parentValueWatch; newVal: [{
and when i try to add the 10' element in the cookies I have this error (only 9 element I am able to store): Cookie '' possibly not set or overflowed because it was too large (4263 > 4096 bytes)! -
I am not able to resolve it..someone can help me?
Thanks
It would be helpful if you could put together a jsfiddle example.
From your code I can see the following issue.
In the ng-repeat section either should use 'items[$index]' or just 'item'.
<table class="table" >
<tr data-ng-repeat="item in items">
<td><span >{{item.title}}</span></td>
<td> <button data-ng-click="addToCookies(item)" data-ng-disabled="item.added" class="btn">
<span data-ng-show="!item.added" class="text-center">Add To cookies</span>
<span data-ng-show="item.added" class="text-center">Added To cookies</span>
</button>
</td>
</tr>
<tr></tr>
</table>
What is the method addToCookies exactly doing? What is $scope.criteria object? It looks like you always modify and add the same object to the cookieItems.
$scope.addToCookies = function (item){
item.added=true;
angular.extend($scope.criteria, item); // what is $scope.criteria?
cookiesItems.addItem($scope.criteria); // will always the same object added to the cookieItems?
$scope.selectedItems.push(item); // why do you have a second list and why you add 'item' and not 'criteria'?
}

Categories

Resources