Button click count for each list item in AngularJS - angularjs

I have a list and I want to get the button click count for each item separately.
I have created an example example but that has increasing all items. Please help. One Important thing, the JSON doesn't have 'count' key.
var myApp = angular.module('myApp',[]);
var jsonInfo = {"count":["one", "two", "three", "four"]}
function MyCtrl($scope) {
$scope.data =jsonInfo;
$scope.counter = 0;
$scope.count = function (inc) {
$scope.counter += inc;
};
}

One way you can do this by Modifying the array in to object array
var jsonInfo = {"count":[{"name":"one",count:0} ,{"name":"two",count:0} ,{"name":"three",count:0} ,{"name":"four",count:0}]}
Now modify the html like this
<li ng-repeat="list in data.count">
<a href="#" ng-click="count(list)">
<span>{{list.name}}</span>
<span style="display: block;">Count: {{list.count}}</span>
</a>
</li>
Then pass the obj as parameter to function and increase the count of that object
function MyCtrl($scope) {
$scope.data =jsonInfo;
$scope.counter = 0;
$scope.count = function (inc) {
inc.count = inc.count + 1
};
}
Demo

Try this
<!DOCTYPE html>
<html ng-app="myApp">
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.1/angular.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<script type="text/javascript">
var myApp = angular.module('myApp', [])
.controller('MyCtrl', function MyCtrl($scope) {
var jsonInfo = [
{
count: 1,
name: "one"
},
{
count: 1,
name: "two"
},
{
count: 1,
name: "three"
},
{
count: 1,
name: "four"
}]
$scope.data = jsonInfo;
$scope.counter = 0;
$scope.count = function (inc) {
inc.count = inc.count + 1;
};
})
</script>
</head>
<body>
<div ng-controller="MyCtrl">
<ul>
<li ng-repeat="list in data">
<a href="#" ng-click="count(list)">
<span>{{list.name}}</span>
<span style="display: block;">Count: {{list.count}}</span>
</a>
</li>
</ul>
</div>
</body>
</html>

Related

Insert checked checkbox value at the end

I have a check box with a button.
When I click button checked, checkbox value should be pushed into an array. But it adds at the beginning of an array. I want to add checked checkbox value at the end of the array when clicking the button.
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.4/angular.min.js"></script>
<script src="https://rawgithub.com/angular-ui/ui-sortable/master/src/sortable.js"></script>
<meta charset="utf-8">
<title>JS Bin</title>
</head>
<body ng-app='test' ng-controller="Test">
<ul>
<li ng-repeat="album in albums">
<input type="checkbox" ng-model="album.selected" value={{album.name}} /> {{album.name}}
</li>
</ul>
<button type='button' ng-click="save()">Save</button><br>
<div ui-sortable="sortableOptionsList[0]" >
{{albumNameArray}}
</div>
<div ui-sortable="sortableOptionsList[0]">
<div class="app" ng-repeat="app in albumNameArray"> {{app.name}}</div>
</div>
</body>
</html>
<script>
angular.module('test', ['ui.sortable'])
.controller('Test', function($scope){
$scope.albums = [{
id: 1,
name: 'test1',
checked : false
},
{
id: 2,
name: 'test2',
checked : false
},
{
id: 3,
name: 'test3',
checked : false
}];
function createOptions (listName) {
console.log('outout');
var _listName = listName;
var options = {
placeholder: "app",
connectWith: ".apps-container",
helper: function(e, item) {
console.log("list " + _listName + ": helper");
return item;
}
};
return options;
}
$scope.sortableOptionsList = [createOptions('A'), createOptions('B')];
$scope.save = function(){
$scope.albumNameArray = [];
angular.forEach($scope.albums, function(album){
console.log(album.selected);
if(album.selected)
{
$scope.albumNameArray.push(album.name);
}
});
}
})
</script>
I have the perfect solution for your query. You just need to make a small change on the logic. Since you want to track the sequence on which the checkboxes are selected, i would suggest you the proper way in AngularJS, using ng-change on the checkbox.
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.4/angular.min.js"></script>
<script src="https://rawgithub.com/angular-ui/ui-sortable/master/src/sortable.js"></script>
<meta charset="utf-8">
<title>JS Bin</title>
</head>
<body ng-app='test' ng-controller="Test">
<ul>
<li ng-repeat="album in albums">
<input type="checkbox" ng-model="album.selected" value={{album.name}} ng-change='trackOrder(album)' /> {{album.name}}
</li>
</ul>
<button type='button' ng-click="save()">Save</button><br>
<div ui-sortable="sortableOptionsList[0]" >
{{albumNameArray}}
</div>
<div ui-sortable="sortableOptionsList[0]">
<div class="app" ng-repeat="app in albumNameArray"> {{app.name}}</div>
</div>
</body>
</html>
<script>
angular.module('test', ['ui.sortable'])
.controller('Test', function($scope){
$scope.albumArray = [];
$scope.albums = [{
id: 1,
name: 'test1',
checked : false
},
{
id: 2,
name: 'test2',
checked : false
},
{
id: 3,
name: 'test3',
checked : false
}];
function createOptions (listName) {
console.log('outout');
var _listName = listName;
var options = {
placeholder: "app",
connectWith: ".apps-container",
helper: function(e, item) {
console.log("list " + _listName + ": helper");
return item;
}
};
return options;
}
$scope.sortableOptionsList = [createOptions('A'), createOptions('B')];
$scope.trackOrder = function(album){
//add album in the array
if(album.selected){
$scope.albumArray.push(album.name);
}else{
//remove album fron the array
var index = $scope.albumArray.indexOf(album.name);
$scope.albumArray.splice(index,1);
}
}
$scope.save = function(){
//if you want the value on albumNameArray on click on save use this else you can
//use the $scope.albumArray directly
$scope.albumNameArray = angular.copy($scope.albumArray);
}
})
</script>
Here is the plunkr link PLUNKR
use unshift.
$scope.albumNameArray.unshift(album.name);

Refresh the pagination after filtering

I have implemented a pagination and a filter based on a criteria function: JSBin:
<!DOCTYPE html>
<html ng-app="plunker">
<head>
<link data-require="bootstrap-css#3.x" data-semver="3.1.1" rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" />
<script data-require="angular.js#*" data-semver="1.2.14" src="https://code.angularjs.org/1.2.14/angular.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/0.11.0/ui-bootstrap-tpls.js"></script>
</head>
<body>
<section class="main" ng-controller="contentCtrl">
<div style="float: right; margin-right: 200px">
has more than 3 letters <input type="checkbox" ng-model="criteria.number" ng-true-value="3" ng-false-value="null" /><br>
</div>
<h3>Existing friends</h3>
<div ng-repeat="friend in filteredFriends | filter: criteriaMatch(criteria)">
{{friend.name}}
</div>
<pagination total-items="totalItems" items-per-page="itemsPerPage" ng-model="currentPage"></pagination>
</section>
</body>
</html>
JavaScript:
var app = angular.module('plunker', ['ui.bootstrap']);
app.factory('friendsFactory', function() {
var o = {
friends: [ {"name":"Jack"}, {"name":"Tim"}, {"name":"Stuart"},
{"name":"Tom"}, {"name":"Frank"}, {"name":"Nicholas"},
{"name":"Jesse"}, {"name":"Amber"}, {"name":"Tom"},
{"name":"Jerry"}, {"name":"Richard"}, {"name":"Mike"},
{"name":"Michael"}, {"name":"Jim"}, {"name":"Louis"}]
};
return o;
});
app.controller('contentCtrl', function ($scope, friendsFactory) {
$scope.friends = friendsFactory.friends;
$scope.totalItems = $scope.friends.length;
$scope.itemsPerPage = 5
$scope.currentPage = 1;
function refresh() {
var begin = (($scope.currentPage - 1) * $scope.itemsPerPage);
var end = begin + $scope.itemsPerPage;
$scope.filteredFriends = friendsFactory.friends.slice(begin, end);
$scope.totalItems = $scope.friends.length;
}
$scope.criteria = { number: "null" };
$scope.criteriaMatch = function (cri) {
return function (friend) {
return ((cri.number === "null") || (friend.name.length > cri.number));
};
};
$scope.$watch('currentPage', refresh);
});
The problem is that, after selecting the filter, it shows the names whose length is greater than 3 page by page. What I want is that, it should recalculate the number of pages, and keep showing 5 good names per page.
Does anyone know how to modify the program to realise this?
Additionally, if I replace "null" by null, it will not work after selecting and deselecting the filter. Does anyone know why?
PS: it is very different from this thread; not a duplication...
Here is a solution: JSBin:
<!DOCTYPE html>
<html ng-app="plunker">
<head>
<meta name="description" content="filter and pagination 1">
<link data-require="bootstrap-css#3.x" data-semver="3.1.1" rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" />
<script data-require="angular.js#*" data-semver="1.2.14" src="https://code.angularjs.org/1.2.14/angular.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/0.11.0/ui-bootstrap-tpls.js"></script>
</head>
<body>
<section class="main" ng-controller="contentCtrl">
<div style="float: right; margin-right: 200px">
has more than 3 letters <input type="checkbox" ng-model="criteria.number" ng-true-value="3" ng-false-value="0" /><br>
</div>
<h3>Existing friends</h3>
<div ng-repeat="friend in filteredFriends | start: (currentPage - 1) * itemsPerPage | limitTo: itemsPerPage">
{{friend.name}}
</div>
<pagination total-items="filteredFriends.length" items-per-page="itemsPerPage" ng-model="currentPage"></pagination>
</section>
</body>
</html>
JavaScript:
var app = angular.module('plunker', ['ui.bootstrap']);
app.factory('friendsFactory', function() {
var o = {
friends: [ {"name":"Jack"}, {"name":"Tim"}, {"name":"Stuart"},
{"name":"Tom"}, {"name":"Frank"}, {"name":"Nicholas"},
{"name":"Jesse"}, {"name":"Amber"}, {"name":"Tom"},
{"name":"Jerry"}, {"name":"Richard"}, {"name":"Mike"},
{"name":"Michael"}, {"name":"Jim"}, {"name":"Louis"}]
};
return o;
});
app.controller('contentCtrl', function ($scope, friendsFactory) {
$scope.friends = friendsFactory.friends;
$scope.criteria = { number: 0 }
$scope.filteredFriends = $scope.friends;
$scope.itemsPerPage = 5
$scope.currentPage = 1;
function refresh() {
$scope.filteredFriends = $scope.friends.filter(function(item){
return item.name.length > $scope.criteria.number;
})
};
$scope.$watch('currentPage', refresh);
$scope.$watch('criteria.number', refresh);
});
app.filter('start', function () {
return function (input, start) {
if (!input || !input.length) { return; }
return input.slice(start);
};
});

about ng-repeat can we bind inside ng-repeat statement

<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
</head>
<body>
<div ng-app="myApp" ng-controller="customersCtrl">
<button ng-click="call('d')">for d</button>
<button ng-click="call('f')">for f</button>
<ul>
<li ng-repeat="x in a.{{replace}}">
{{x}}
</li>
</ul>
</div>
<script>
var app = angular.module('myApp', []);
app.controller('customersCtrl', function($scope) {
$scope.a = {
d:[1,2,3,4,5],
f:[6,7,8,9]
};
$scope.call = function(val) {
$scope.replace='val';
}
});
</script>
</body>
</html>
I'm trying to add dynamically the values to ng-repeat content, but it's not working, please do help
can we add dynamically values to ng-repeat itself so we can change the iterating values every time by simply changing one value like above, if not is there any better ideas
The following snippet can help you.
<!DOCTYPE html>
<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js">
</script>
<body>
<div ng-app="myApp" ng-controller="customersCtrl">
<button ng-click="call('d')">for d</button>
<button ng-click="call('f')">for f</button>
<ul>
<li ng-repeat="x in a[replace]">
{{x}}
</li>
</ul>
</div>
<script>
var app = angular.module('myApp', []);
app.controller('customersCtrl', function ($scope) {
$scope.a = {
d: [1, 2, 3, 4, 5],
f: [6, 7, 8, 9]
}
$scope.call = function (val) {
$scope.replace = val;
}
});
</script>
</body>
</html>
Explanation :
$scope.replace=val; //Assign the variable and not a string
<li ng-repeat="x in a[replace]"> // No need to use braces are you are in an ng tag already
Instead of passing strings you can pass the values in the call function then assign those values to $scope.replace which then update your ng-repeat
<!DOCTYPE html>
<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"> </script>
<body>
<div ng-app="myApp" ng-controller="customersCtrl">
<button ng-click="call(a.d)">for d</button>
<button ng-click="call(a.f)">for f</button>
<ul>
<li ng-repeat="x in replace">
{{x}}
</li>
</ul>
</div>
<script>
var app = angular.module('myApp', []);
app.controller('customersCtrl', function($scope) {
$scope.a = {
d: [1,2,3,4,5],
f: [6,7,8,9]
}
$scope.call = function(val){
$scope.replace=val;}
}
);
</script>
</body>
</html>

Diamond shaped question mark character appears after when I use "limitTo" filter in AngularJS app

I have an issue while loading comments (with emoji) via API.
<!doctype html>
<html ng-app="app">
<head>
<meta charset="utf-8">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<script src="./angular-1.2.15.js"></script>
<!-- ... -->
</head>
<body>
<!-- ... -->
<ul>
<li ng-repeat="comment in comments">
<span ng-bind="comment.Author"></span>
<span ng-bind="comment.Description"></span>
</li>
</ul>
<!-- ... -->
<script>
angular.module('app', []);
// ...
</script>
</body>
</html>
Before limitTo filter everything goes as expected:
<span>John Doe</span>
<span>Hey, how are you? 😃😄😅😆😉😊😋😎😍😘😗😙😚☺😇😐😑😆😶😏😣😥😮😯😪😫😴😌😛😜😝😒😓😔😕😲😷😖😞😟</span>
But, when I try to apply limitTo filter, something goes wrong:
<span>John Doe</span>
<span>Hey, how are you? 😃😄�</span>
What am I doing wrong? Any ideas?
Here is the demo app:
var app = angular.module('myApp', []);
app.filter('range', function () {
return function(input, total) {
total = parseInt(total);
for (var i=0; i<total; i++) {
input.push(i);
}
return input;
};
});
app.controller('DemoController', ['$scope', function ($scope) {
$scope.comment = {
Author: "John Doe",
Description: "Hey, how are you? 😃😄😅😆😉😊😋😎😍😘😗😙😚☺😇😐😑😆😶😏😣😥😮😯😪😫😴😌😛😜😝😒😓😔😕😲😷😖😞😟"
};
}]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.15/angular.min.js"></script>
<div ng-app="myApp">
<div ng-controller="DemoController">
<ul>
<li ng-repeat="i in [] | range:78" ng-init="limit = 20+i">
<div ng-bind="comment.Author"></div>
<span ng-bind="comment.Description | limitTo: limit"></span> (<span ng-bind="limit"></span>)
</li>
</ul>
</div>
</div>
If you try to get the length of characters of a single emoji in http://www.charactercountonline.com then it will show 2 characters for normal emoji and 1 character in small emoji. So because using limit, one character is missed so it show a question mark sign.
var app = angular.module('myApp', []);
app.filter('range', function () {
return function(input, total) {
total = parseInt(total);
for (var i=0; i<total; i++) {
input.push(i);
}
return input;
};
});
app.controller('DemoController', ['$scope', function ($scope) {
$scope.setLimit = function(i){
$scope.limit = 20+i;
}
$scope.comment = {
Author: "John Doe",
Description: "Hey, how are you? 😃😄😅😆😉😊😋😎😍😘😗😙😚☺😇😐😑😆😶😏😣😥😮😯😪😫😴😌😛😜😝😒😓😔😕😲😷😖😞😟"
};
}]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.15/angular.min.js"></script>
<div ng-app="myApp">
<div ng-controller="DemoController">
<ul>
<li ng-repeat="i in [] | range:78" ng-init="setLimit(i)">
<div ng-bind="comment.Author"></div>
<span ng-bind="comment.Description | limitTo: limit"></span> (<span ng-bind="limit"></span>)
</li>
</ul>
</div>
</div>

Howto access the passed variable in a custom directive with JavaScript?

I have made a custom directive and can access the passed variable in the direct.template within double squiqqly brackets like this directive.template = '<input/>{{text.incorrectAnswers}}' but how do I access it in JavaScript so I can change it and then pass it back into my directive.template?
<html ng-app="mainApp">
<head>
<script src="http://code.jquery.com/jquery-1.11.2.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.26/angular.min.js"></script>
<script src="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/js/bootstrap.min.js"></script>
<link href="http://maxcdn.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css" rel="stylesheet">
</head>
<body ng-controller="mainController" style="padding: 20px 0">
<div class="col-xs-8">
<div class="panel panel-default">
<div class="panel-heading">Company Info</div>
<div class="panel-body">
<div ng-repeat="text in texts">
<div data-show-phrase data-text="text"></div>
</div>
</div>
</div>
</div>
<script>
var mainApp = angular.module('mainApp', []);
mainApp.controller('mainController', function ($scope) {
$scope.texts = [
{
body: 'Customer 1 is from [##blank] and Customer 2 is from [##blank].',
correctAnswers: 'Berlin;Hamburg',
incorrectAnswers: 'Stuttgart;Munich;Frankfurt'
},
{
body: 'Company 3 is located in [##blank].',
answers: 'Bremen',
incorrectAnswers: 'Hannover;Dresden;Stuttgart'
}
];
});
mainApp.directive('showPhrase', function () {
var directive = {};
directive.restrict = 'A';
directive.scope = {
text: '=text'
};
//var parts = incorrectAnswers.split(';'); //Error: incorrectAnswers is not defined
//var parts = $scope.incorrectAnswers.split(';'); //Error: incorrectAnswers is not defined
var parts = directive.incorrectAnswers.split(';'); //Error: incorrectAnswers is not defined
directive.template = '<input/>{{text.body}}';
return directive;
});
</script>
</body>
</html>
2-way bound properties available as a part of the scope object and that cannot be accessed during the creation of a directive, because no scope exists yet. You need to at least wait till linking phase or in the controller to access the scope and its properties. If you are using controllerAs syntax (with 1.3.x) then you would turn on bindToController:true to be able to access it as properties of the controller instance. And as long as you use bindings in your template, angular will take care of updating the template for dynamic changes in the bound properties.
Example:-
mainApp.directive('showPhrase', function() {
var directive = {};
directive.restrict = 'A';
directive.scope = {
text: '='
};
/*Linking function*/
directive.link = function(scope, elm) {
scope.parts = scope.text.incorrectAnswers.split(';');
console.log(parts)
}
directive.template = '<div><input/>{{text.body}} <ul><li ng-repeat="part in parts">{{part}}</li></ul></div>';
return directive;
});
var mainApp = angular.module('mainApp', []);
mainApp.controller('mainController', function($scope) {
$scope.texts = [{
body: 'Customer 1 is from [##blank] and Customer 2 is from [##blank].',
correctAnswers: 'Berlin;Hamburg',
incorrectAnswers: 'Stuttgart;Munich;Frankfurt'
}, {
body: 'Company 3 is located in [##blank].',
answers: 'Bremen',
incorrectAnswers: 'Hannover;Dresden;Stuttgart'
}];
});
mainApp.directive('showPhrase', function() {
var directive = {};
directive.restrict = 'A';
directive.scope = {
text: '='
};
directive.link = function(scope, elm) {
scope.parts = scope.text.incorrectAnswers.split(';');
console.log(parts)
}
directive.template = '<div><input/>{{text.body}} <ul><li ng-repeat="part in parts">{{part}}</li></ul></div>';
return directive;
});
<html ng-app="mainApp">
<head>
<script src="http://code.jquery.com/jquery-1.11.2.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.26/angular.min.js"></script>
<script src="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/js/bootstrap.min.js"></script>
<link href="http://maxcdn.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css" rel="stylesheet">
</head>
<body ng-controller="mainController" style="padding: 20px 0">
<div class="col-xs-8">
<div class="panel panel-default">
<div class="panel-heading">Company Info</div>
<div class="panel-body">
<div ng-repeat="text in texts">
<div data-show-phrase data-text="text"></div>
</div>
</div>
</div>
</div>
<script>
</script>
</body>
</html>

Resources