Assign css class using ng-class in angular js - javascript

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>

Related

AngularJS: ng-repeat without similar key

I have list of objs:
[{
key:test1
name: name1
},
{
key:test1
name: name2
},
{
key:test2
name: name3
}]
And i use ng-repeat to display it:
<tr ng-repeat=item in list>
<td>{{item.key}}</td>
<td>{{item.name}}</td>
</tr>
Is it possible to combine values with similar keys without changing the structure? not to be displayed twice test1 in my case
now:
test1 : name1
test1 : name2
test2 : name3
desired result:
test1 : name1
_____ name2
test2 : name3
You can use groupBy filter:
angular.module('app', ['angular.filter']).controller('ctrl', function($scope){
$scope.list = [{
key:'test1',
name: 'name1'
}, {
key:'test1',
name: 'name2'
},{
key:'test1',
name: 'name3'
},{
key:'test2',
name: 'name4'
}];
})
table, th, td {
border: 1px solid black;
border-collapse: collapse;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-filter/0.5.16/angular-filter.js"></script>
<table ng-app='app' ng-controller='ctrl'>
<tbody>
<tr ng-repeat-start="(key, value) in list | groupBy: 'key'">
<td>{{key}}</td>
<td>{{value[0].name}}</td>
</tr>
<tr ng-repeat-end ng-repeat='item in value.splice(1)'>
<td></td>
<td>{{item.name}}</td>
</tr>
</tbody>
</table>
ng-repeat="item in list | unique:'key'"
Here is how you can achieve the common key value in a same place using angular-filter:
angular.module('app',['angular.filter']).controller('mainCtrl', function($scope){$scope.list = [{
key:'test1',
name: 'name1'
},
{
key:'test1',
name: 'name2'
},
{
key:'test2',
name: 'name3'
}]
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.22/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-filter/0.5.16/angular-filter.min.js"></script>
<div ng-app='app' ng-controller='mainCtrl'>
<div ng-repeat="(key, value) in list | groupBy: 'key'">
<span ng-repeat='val in value'>{{val.name}} </span>
</div>
</div>
Before using ng-repeat update the list.
function rd(o, k, v) {
var n = [];
var l = {};
for(var i in o) {
if (l.hasOwnProperty(o[i][k])){
o[i][v] = l[o[i][k]][v]+ " " + o[i][k]
l[o[i][k]] = o[i]
} else{
l[o[i][k]] = o[i];
}
}
for(i in l) {
n.push(l[i]);
}
return n;
}
var list = rd(arr, "key", "name");
You can try this:
var app = angular.module('myApp', ['angular.filter']);
app.controller('myCtrl', function($scope) {
$scope.items = [{
"key":"test1",
"name": "name1"
},
{
"key":"test1",
"name": "name2"
},
{
"key":"test2",
"name": "name3"
}];
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
<script
src="https://cdnjs.cloudflare.com/ajax/libs/angular-filter/0.5.16/angular-filter.min.js"></script>
<div ng-app="myApp" ng-controller="myCtrl">
<div ng-repeat="item in items | groupBy: 'key'">
<h3>Key : {{item[0].key}}</h3>
<p>Names : <span ng-repeat='i in item'>{{i.name}} </span></p>
</div>
</div>

limit the number of items shown in 2nd ng-repeat

i listed category from json data.i have listed number of sub category under category but i want to list only 3 sub category under category.if i click view more option i want to list corresponding sub category depends on category in modal popup.
i have returned created div depends on parentid zero
$scope.cat = categories.filter(function(category) {
return category && category.parentid === 0
});
i have updated my code in plunker.
http://plnkr.co/edit/Vh1NzYf0qjUkIygLUEJk?p=preview
You can do it by simlpe filter:
<div ng-repeat="childItem in content | filter: item.id | limitTo: 3">
Demo 1 plunker
It also will get rid of using ng-if="childItem.parentid === item.id"
Example:
<div ng-repeat="item in cat">
{{item.name}}
<div ng-repeat="childItem in content | filter: item.id | limitTo: 3">
<div style="margin-left: 20px;" >
{{childItem.name}}
</div>
</div>
</div>
If you want to handle view more, you can write:
<div ng-repeat="childItem in content | filter: item.id | limitTo: limit">
and:
$scope.limit = 3;
$scope.viewMore = function(){
$scope.limit = 100;
}
Demo 2 plunker
[EDIT]
if you want to update view more per sub-category, you need bind limit to your data:
<body ng-controller="MainCtrl">
<div ng-repeat="item in cat">
{{item.name}}
<div ng-repeat="childItem in content | filter: item.id | limitTo: item.limit">
<div style="margin-left: 20px;" >
{{childItem.name}}
</div>
</div>
<a href="" ng-click="viewMore(item)"
ng-if="item.limit == 3">view more</a>
</div>
</body>
and:
$scope.viewMore = function(item){
item.limit = 100;
}
Demo 3 plunker
Update
If you want a show more functionality refer the below Plunkr.
Plunkr
This will do the job. I have added a custom filter that takes the parent.Id as an argument and check the child's parent Id (which was done before by the ng-if). Then I use angular's limit to: 3 filter to limit the results to only 3 items.
Plunkr
Code:
$scope.searchMe = function(statusId) {
return function(user) {
return user.parentid === statusId;
}
}
and the ng-repeat should look like
<div ng-repeat="item in cat">
{{item.name}}
<div ng-repeat="childItem in content | filter: searchMe(item.id) | limitTo: 3">
<div style="margin-left: 20px;">
{{childItem.name}}
</div>
</div>
<a ng-click="open_modalpopup()">view more</a>
</div>
References:
Limit To
passing arguements to angularJS filters
UPDATE -
As per your latest requirement -
if i click view more i want to list all corresponding sub category
depends on category
I update the plnkr to show all categories in a popup once user clicked on View More button.
Updated Plnkr - http://plnkr.co/edit/OUvzqWdfZuQnZpbXWSRW?p=preview
As per your requirement I believe you need to show/hide sub categories on the basis of button click available under specific category.
I re arranged your data and rather than saving it into multiple objects, I am using a singular object newcat to store and manage the UI.
Working Plnkr -
http://plnkr.co/edit/F6MlkMWOJ2b7isRAM1u6?p=preview
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
var data = [{
id: 1,
name: 'mobile',
parentid: 0
}, {
id: 2,
name: 'samsung',
parentid: 1
}, {
id: 3,
name: 'moto',
parentid: 1
}, {
id: 4,
name: 'redmi',
parentid: 1
}, {
id: 5,
name: 'honor',
parentid: 1
}, {
id: 6,
name: 'nokia',
parentid: 1
},
{
id: 7,
name: 'tv',
parentid: 0
}, {
id: 8,
name: 'tv1',
parentid: 7
}, {
id: 9,
name: 'tv2',
parentid: 7
}, {
id: 10,
name: 'tv3',
parentid: 7
}, {
id: 11,
name: 'tv4',
parentid: 7
}, {
id: 12,
name: 'tv5',
parentid: 7
}];
var categories = data;
$scope.title = 'Show Hide Subcategories';
$scope.cat = categories.filter(function(category) {
return category && category.parentid === 0
});
$scope.newcat = angular.extend($scope.cat, {});
angular.forEach($scope.cat, function(cat, key){
var tmpIndex = 0;
var tmpdata = categories.filter(function(category) {
if(cat.id === category.parentid) {
category.indexVal = tmpIndex;
category.isShow = tmpIndex < 3 ? true : false;
tmpIndex++;
return true;
}
})
$scope.newcat[key]['subCat'] = tmpdata;
$scope.newcat[key]['moreclicked'] = false;
})
$scope.showMore = function(index) {
if(!$scope.newcat[index]['moreclicked']) {
angular.forEach($scope.newcat[index].subCat, function(subcat, key) {
subcat.isShow = true;
})
$scope.newcat[index]['moreclicked'] = true;
}
else {
angular.forEach($scope.newcat[index].subCat, function(subcat, key) {
if(key > 2)
subcat.isShow = false;
})
$scope.newcat[index]['moreclicked'] = false;
}
};
});
<!DOCTYPE html>
<html ng-app="plunker">
<head>
<meta charset="utf-8" />
<title>AngularJS Plunker</title>
<script>
document.write('<base href="' + document.location + '" />');
</script>
<link rel="stylesheet" href="style.css" />
<script data-require="angular.js#1.5.x" src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.11/angular.min.js" data-semver="1.5.11"></script>
<script src="app.js"></script>
</head>
<body ng-controller="MainCtrl">
<h3 ng-bind="title"></h3>
<div ng-repeat="cat in newcat">
<b>{{cat.name}}</b>
<div ng-repeat="subcat in cat.subCat">
<div style="margin-left: 20px;" ng-if="subcat.isShow">
{{subcat.name}}
</div>
</div>
<button ng-click="showMore($index)" ng-bind="!cat.moreclicked ? 'View More': 'View Less'"></button>
</div>
</body>
</html>

how to count the checkbox which was checked using angular?

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>

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