how to count the checkbox which was checked using angular? - javascript

Here, I used $watch to display the counter value.
But the counter value not increased yet,
To Count,
$scope.$watch('items', function(items){
var selectedItems = 0;
angular.forEach(items, function(item){
selectedItems += item.selected ? 1 : 0;
})
$scope.selectedItems = selectedItems;
}, true);
In UI,
<div class="col-sm-4" ng-repeat="item in items">
<label class="chkbox-holder cbox mbot10" for="List-{{$index}}"><input ng-model="item.Selected" type="checkbox" id="List-{{$index}}"><label for="List-{{$index}}"></label>{{item.name}}</label>
</div>
To display the counter value,
<div>Selected Items Length: {{selectedItems}}</div>
But still the counter is 0;
JSON Value from http service is,
[
{
"id": 1,
"refCode": "",
"name": "pragadees"
},
{
"id": 2,
"refCode": "",
"name": "pragadees"
}......]
Can anyone please help on this.

You've just got a typo error. Your markup is bound to item.Selected while your JavaScript is checking for item.selected. Renaming them properly solves your problem. I'd recommend using lower key inside ot html.
<input ng-model="item.selected" type="checkbox" id="List-{{$index}}">
^-- See here
Demo

first of all, you got a typo in your ng-model, it is item.selected not item.Selected that's maybe why it does not match nothing...
And this is how i'll write it, using basic angular two way data binding, no extra counters, watches, triggers, ....
angular.module('myApp', []);
angular.module('myApp').controller('Ctrl', ['$scope', function($scope) {
$scope.items = [{
name: "Doe"
}, {
name: "Adam"
}, {
name: "Ado"
}, {
name: "Brown"
}, {
name: "Heather"
}, {
name: "Stan"
}];
$scope.itemsSelected = function() {
return $scope.items.filter(function(i) {
return i.selected
}).length;
}
}
]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body ng-app="myApp" ng-controller="Ctrl">
<h2>current active selected options {{ itemsSelected() }}</h2>
<ul>
<div ng-repeat="item in items">
<label for="List-{{$index}}">
<input ng-model="item.selected" type="checkbox" id="List-{{$index}}">
<label for="List-{{$index}}"></label>{{item.name}}</label>
</div>
</ul>
</body>

You can use ng-change instead:
var app = angular.module("app", []);
app.controller("myCtrl", function($scope) {
$scope.items = [
{name: 'A', value: 'a'},
{name: 'B', value: 'b'},
{name: 'C', value: 'c'},
{name: 'D', value: 'd'},
{name: 'E', value: 'e'}
];
$scope.counter = 0;
$scope.change = function(e) {
if(e){
$scope.counter +=1;
}else{
if($scope.counter > 0) $scope.counter -=1;
}
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="myCtrl">
<div class="col-sm-4" ng-repeat="item in items">
<label class="chkbox-holder cbox mbot10" for="List-{{$index}}">
<input ng-model="item.Selected" type="checkbox" id="List-{{$index}}"
ng-change="change(item.Selected)">
<label for="List-{{$index}}"></label>{{item.name}}</label>
</div>
Counter: {{counter}}
</div>

Related

Assign css class using ng-class in angular js

I'm using angularjs and I have data like this :
$scope.users = [{
name: "Pratik"
queue: [{number: "199"},{number: "111"}],
status: "OK"
}]
My view :
.available{
background-color: #00226f;
color: #f8f8f8;
}
<div class="col-xs-12 col-sm-3" ng-repeat="user in users">
<span ng-class="{'available': user.queue[0].number == 111}" class="badges ">111</span>
</div>
My problem is that I want to assign the class "available" if the queue array in users contains the number "111" at any index. In the users array the number:"111" may appear at any index so in the view I can't always use user.queue[1].number == 111 or user.queue[1].number == 111 to assign the class. I want a solution which will check if the queue array contains number:"111" and assign the class of available accordingly.
I tried to do it like this : ng-class="{'available': user.queue[i].number == 111}" but it's not working. How do I do it?
This my current workaround to apply the class:
ng-class="{'available': user.queue[0].number == 111 || user.queue[1].number == 111}"
try below code snippet
can achieve by using lodash js also using _.filter
_.filter(array, { 'number': '111' } )
Ref: https://lodash.com/docs/4.17.11#find
var myApp = angular.module('myApp',[]);
function MyCtrl($scope) {
$scope.findObjectByKey = function(array, key, value) {
for (var i = 0; i < array.length; i++) {
if (array[i][key] === value) {
return array[i];
}
}
return null;
};
$scope.users = [{
name: "Pratik",
queue: [{number: "199"},{number: "666"}],
status: "OK"
},
{
name: "Pratik 2",
queue: [{number: "111"},{number: "555"}],
status: "OK 2"
},
{
name: "Pratik 3",
queue: [{number: "999"},{number: "888"}],
status: "OK 3"
}
];
$scope.searcInArray = function(array){
// var obj = $scope.findObjectByKey(array, 'number', '111');
// using loadsh
var obj = _.filter(array, { 'number': '111' } );
return obj.length > 0;
};
}
.available{
background-color: #00226f;
color: #f8f8f8;
}
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
</head>
<body>
<div ng-app="myApp" ng-controller="MyCtrl">
<div class="col-xs-12 col-sm-3" ng-repeat="user in users">
<span ng-class="{'available' : searcInArray(user.queue)}" class="badges ">111</span>
</div>
</div>
</body>
</html>
You have to add use ng-repeat to loop all queue and find how has item.number == '111'
<div class="col-xs-12 col-sm-3" ng-repeat="user in users">
<div ng-repeat="item in user.queue">
<span ng-class="{'available': item.number == '111'}" class="badges ">111</span>
</div>
</div>
NOTE!
if you want show only the item.number == '111' you can use ng-hide/show
To check that condition where 111 appears at any index the easy fix could be to call a function that will check that property in the array and return true or false based on the condition. Something like below:
var app = angular.module('myApp', []);
app.controller('MainCtrl', ['$scope', function($scope){
$scope.users = [{
name: "Pratik",
queue: [{
number: "111"
}, {
number: "119"
}],
status: "OK"
},
{
name: "Pratik123",
queue: [{
number: "199"
}, {
number: "185"
}],
status: "OK"
}];
$scope.checkQueue = function(queue){
return queue.find(({number})=>number === '111');
}
}]);
.available {
background-color: #00226f;
color: #f8f8f8;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp" ng-controller="MainCtrl">
<div class="col-xs-12 col-sm-3" ng-repeat="user in users">
<span ng-class="{'available': checkQueue(user.queue)}" class="badges ">{{user.name}}</span>
</div>
</div>

ng-filter by string tokens of input

I have multiple input fields that I am currently filtering a ng-repeat by like so
...
<input class="form-control" type="text" ng-model="itemFilter.id" />
<input class="form-control" type="text" ng-model="itemFilter.attr1" />
<input class="form-control" type="text" ng-model="itemFilter.attr2" />
...
<tr ng-repeat="item in $scope.items | filter:itemFilter | orderBy: '-id' track by $index"> <td>{{item.id}}</td>
</tr>
...
How can I filter on the tokens from each the inputs?
For example, if itemFilter.id = "1 2 3" the ng-repeat would include ids that contain 1,2, or 3
As #Andrei mentioned, you have to write your own custom filter to achieve the desired functionality. The code below illustrates how it could be created and how the parameters could be passed to perform custom filtering logic.
The idea here is to build an array of tokens for each object property using split() and then check if item satisfy the filters using filter() on filters array:
(function (angular) {
'use strict';
angular.module("demo", [])
.filter("filterByTokens", function () {
return function (items, obj) {
var separator = obj.separator || ' ';
var keys = Object.keys(obj).filter(function (key) {
return key !== 'separator'
});
//create filters array
var filters = keys.map(function (key) {
return {
key: key,
values: (obj[key] || '').split(separator).filter(function (val) {
return !!val;
})
}
});
if (!filters.length) return items;
return items.filter(function (item) {
return filters.filter(function (f) {
return !f.values || !f.values.length || (f.values.indexOf(item[f.key].toString()) > -1);
}).length === filters.length; // we want to check if all filters are satisfied
});
};
})
.controller('Demo', [function Demo() {
var vm = this;
vm.itemFilter = {id:'1 3 5 2 6', name: 'Test5 Test6', separator: ' '};
vm.items = [
{id: 1, name: 'Test1'}, {id: 2, name: 'Test2'}, {id: 3, name: 'Test3'},
{id: 4, name: 'Test4'}, {id: 5, name: 'Test5'}, {id: 6, name: 'Test6'},
];
}]);
})(angular);
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
<div ng-app="demo" ng-controller="Demo as vm">
<hr/>
<input class="form-control" type="text" ng-model="vm.itemFilter.id" placeholder="itemFilter.ids"/>
<input class="form-control" type="text" ng-model="vm.itemFilter.name" placeholder="vm.itemFilter.names"/>
<hr/>
<code>Filter: {{vm.itemFilter}}</code>
<hr/>
<div ng-repeat="item in vm.items | filterByTokens:vm.itemFilter | orderBy: '-id' track by item.id">
<span>
{{item.id}}
</span>
<span>
{{item.name}}
</span>
</div>
</div>
P.S.: Possibly not the most performant solution, but just a demonstration of how this could be achieved using filters.

Get ngrepeat $index with getElementById()

I am new to AngularJs and I am curious on what is the best approach to getting then index of an ngrepeat on an input and comparing to see if the new string is different from the original value:
js:
var checkIfDataSampleHasChanged = document.getElementById('dsField' + i).value;
console.log(checkIfDataSampleHasChanged);
console.log($scope.currentSchema)
if (checkIfDataSampleHasChanged != $scope.currentSchema.sDataSamples.dsName) {
console.log("hello there")
$scope.currentSchema.sDataSamples.dsName = checkIfDataSampleHasChanged;
}
html:
<fieldset ng-repeat="ds in currentSchema.sDataSamples track by $index">
<label for="{{dsField$index}}" style="width:400px;">
Data Sample Name ({{ds.dsFileName}}):</label>
<input name="{{dsField$index}}" type="text" style="width: 400px;" ng-model="currentSchema.sDataSamples[$index].dsName" value="{{ds.dsName}}" />
<br>
<br>
</fieldset>
You can use a data to hold the initial value and then compare the changed value. You can do this in pure angularjs constructs without using document.getElementById and other hacks:
angular
.module('app', [])
.controller('AppController', function ($scope) {
var initialSample = [
{id: 1, name: 'Abc'},
{id: 2, name: 'def'},
{id: 3, name: 'ghi'},
{id: 4, name: 'jkl'},
{id: 5, name: 'mno'}
];
$scope.sample = angular.merge([], initialSample);
$scope.checkIfValueChanged = function ($index) {
var isValChanged = initialSample[$index].name !== $scope.sample[$index].name;
console.log(isValChanged);
if (isValChanged) {
alert("Value has changed");
} else {
alert("Value has not changed");
}
};
$scope.changeVal = function(){
var randInt = Math.floor(Math.random() * 5);
console.log(randInt);
$scope.sample[randInt].name = "Lorem ipsum";
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.0/angular.min.js"></script>
<div ng-app='app' ng-controller='AppController'>
<ul>
<li ng-repeat="item in sample" ng-click="checkIfValueChanged($index)">
{{item.name}}
</li>
</ul>
<button ng-click="changeVal()"> Change random value </button>
</div>

How do i implement a sliding filter on ng-repeat in angularjs

I am trying to implement a simple sliding filter in angular, but my ng-repeat does not seeem to be responding
The fiddle for this is here http://jsfiddle.net/zn4b89n0/1/
I have tried the following
HTML
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.3/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/0.13.4/ui-bootstrap-tpls.min.js"></script>
<script src="https://rawgit.com/rzajac/angularjs-slider/master/dist/rzslider.js"></script>
<div ng-app="myapp">
<div ng-controller="TestController as vm">
<p>Price 1: {{vm.priceSlider1.value}}</p>
<rzslider rz-slider-model="vm.priceSlider1.value" rz-slider-floor="vm.priceSlider1.floor" rz-slider-ceil="vm.priceSlider1.ceil"></rzslider>
<ul ng-repeat="friend in vm.friends ">
<li>{{friend.name | filter:filterFn}}</li>
</ul>
</div>
</div>
JS
var myApp = angular.module('myapp', ['rzModule', 'ui.bootstrap']);
myApp.controller('TestController', TestController);
function TestController($scope, $timeout) {
var vm = this;
vm.priceSlider1 = {
floor: 80,
ceil: 100,
value: 85
};
vm.friends = [
{ name: "Peter", age: 20 },
{ name: "Pablo", age: 55 },
{ name: "Linda", age: 20 },
{ name: "Marta", age: 37 },
{ name: "Othello", age: 20 },
{ name: "Markus", age: 32 }
];
vm.filterFn = function(friend)
{
// Do some tests
if(friend.age >= vm.priceSlider1.value )
{
return true; // this will be listed in the results
}
return false; // otherwise it won't be within the results
};
vm.refreshSlider = function () {
$timeout(function () {
$scope.$broadcast('rzSliderForceRender');
});
};
}
How do i get this to work, thank you for any and all assistance
You should use your filter in ng-repeat and execute the filter:
<ul ng-repeat="friend in vm.friends | filter: vm.filterFn() ">
<li>{{friend.name}}</li>
</ul>
You can simplify the filter function:
vm.filterFn = function()
{
return function(item){
//return the whether age attribute of each item (friend) is greater than your value
return item['age'] >= vm.priceSlider1.value;
}
};
Here you can try the updated fiddle: http://jsfiddle.net/Ln9cgrve/
I hope that solves your problem...
Looks like the problem in ngRepeat part. It should be
<ul ng-repeat="friend in vm.friends | filter:vm.filterFn">
<li>{{friend.name}}</li>
</ul>
Note, filter is in ngRepeat directive and also filter function should be referred as vm.filterFn.

Angular ng-repeat for duplicates

I use Angular, this is my view:
<div class="col-sm-6" ng-repeat="contact in service.contacts">
<label class="control-label mb10">{{contact.textDescription | decodeURIComponent}}</label>
<select multiple="multiple" selectize>
<option>{{contact.value}}</option>
</select>
</div>
I have one problem and I can't figure out a way to solve it. For contact.textDescription, I need to put only unique values, so if that contact.textDescription is duplicate, don't create field twice, but add that contact.value to options of that same contact.textDescription which already exists.. So, something like this:
if(contact.textDescription is duplicate) {
contact.value.addTo(contact.textDescription which already exists)
}
Maybe some filter to apply or?
By the understanding of what you mentioned I think the filter mention in the following answer will help you to do what you want
Use this link to go to the question
You can use ng-options to group and display unique value.
You can use uniqFilter of angular-filter module.
Usage: collection | unique: 'property' or nested.property
Aliases: uniq
Example:
JS:
function MainController ($scope) {
$scope.orders = [
{ id:1, customer: { name: 'John', id: 10 } },
{ id:2, customer: { name: 'William', id: 20 } },
{ id:3, customer: { name: 'John', id: 10 } },
{ id:4, customer: { name: 'William', id: 20 } },
{ id:5, customer: { name: 'Clive', id: 30 } }
];
}
HTML:
<th>Customer list:</th>
<tr ng-repeat="order in orders | unique: 'customer.id'" >
<td> {{ order.customer.name }} , {{ order.customer.id }} </td>
</tr>
RESULT:
Customer list:
- John 10
- William 20
- Clive 30
Grouping your contacts by textDescription should resolve your problem. Try something like this:
html:
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Example - GroupBy Filter</title>
<script src="angular-1.4.7.min.js"></script>
<script src="script.js"></script>
</head>
<body ng-app="app">
<div ng-controller="MainController">
<div ng-repeat="(key, contacts) in (service.contacts | groupBy: 'textDescription')">
<label class="control-label">{{key}}</label>
<select multiple="multiple" selectize>
<option ng-repeat="contact in contacts">{{contact.value}}</option>
</select>
</div>
</div>
</body>
script.js:
var app = angular.module("app", []);
app.controller("MainController", function ($scope) {
$scope.service = {};
$scope.service.contacts = [{
"textDescription": "td1",
"value": "1"
}, {
"textDescription": "td2",
"value": "2"
}, {
"textDescription": "td3",
"value": "3"
}, {
"textDescription": "td1",
"value": "4"
}, {
"textDescription": "td3",
"value": "5"
}, {
"textDescription": "td1",
"value": "6"
}];
});
app.filter('groupBy', function () {
var results={};
return function (data, key) {
if (!(data && key)) return;
var result;
if(!this.$id){
result={};
}else{
var scopeId = this.$id;
if(!results[scopeId]){
results[scopeId]={};
this.$on("$destroy", function() {
delete results[scopeId];
});
}
result = results[scopeId];
}
for(var groupKey in result)
result[groupKey].splice(0,result[groupKey].length);
for (var i=0; i<data.length; i++) {
if (!result[data[i][key]])
result[data[i][key]]=[];
result[data[i][key]].push(data[i]);
}
var keys = Object.keys(result);
for(var k=0; k<keys.length; k++){
if(result[keys[k]].length===0)
delete result[keys[k]];
}
return result;
};
});
Now you have all the contacts grouped by textDescription, so the field for it (<label>) is created only once and the values are added to <option> tags

Categories