Angular ng-repeat for duplicates - javascript

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

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>

Multi level json filter in angular js

I am new in angular js i want to put filter in ng-repeat i have json like this
var data = [
{name:test1,b1:{lastValue:0},b2:{lastValue:6},b3:{lastValue:6},b4:{lastValue:0}}
{name:test2,b1:{lastValue:6},b2:{lastValue:0},b3:{lastValue:6},b4:{lastValue:0}}
{name:test3,b1:{lastValue:6},b2:{lastValue:0},b3:{lastValue:6},b4:{lastValue:0}}
]
I want to put filter on lastValue i tested like this
ng-repeat = "d in data | filter:{*.lastValue:filterStatus}"
filterStatus // contain value of filter which user selected but its not working
I don't know how to do this i tried google but nothing found please help me
<input ng-model="filterStatus" type="text">
your filterStatus should hold model value
ng-repeat = "d in data | filter:filterStatus"
var app = angular.module("Profile", []);
app.controller("ProfileCtrl", function($scope) {
$scope.filter_val = {}
$scope.data = [{
name: 'test1',
b1: {
lastValue: 0
},
index: 'b1'
}, {
name: 'test2',
b2: {
lastValue: 6
},
index: 'b2'
}, {
name: 'test3',
b3: {
lastValue: 6
},
index: 'b3'
}, {
name: 'test4',
b4: {
lastValue: 0
},
index: 'b4'
}, {
name: 'test5',
b5: {
lastValue: 89
},
index: 'b5'
}, {
name: 'test6',
b6: {
lastValue: 68
},
index: 'b6'
}]
$scope.own_filter = function(val) {
if (!$scope.filter_val.value)
return true;
else {
return (String(val[val['index']]['lastValue'] || '').indexOf($scope.filter_val.value) != -1)
}
}
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body ng-app="Profile" ng-controller="ProfileCtrl">
<input type="text" ng-model="filter_val.value" placeholder="Enter Last Value">
<div class="row" ng-repeat="event in data |filter:own_filter track by $index ">
<h4>{{'Name : ' + event.name}}------{{'Last Value : '+event[event['index']]['lastValue']}}</h4>
</div>
</body>
Use {$:filterStatus} construction:
angular.module('app', []).controller('ctrl',function($scope){
$scope.data = [
{name:'test1',b1:{lastValue:1},b2:{lastValue:6},b3:{lastValue:6},b4:{lastValue:0}},
{name:'test2',b1:{lastValue:2},b2:{lastValue:0},b3:{lastValue:6},b4:{lastValue:0}},
{name:'test3',b1:{lastValue:3},b2:{lastValue:0},b3:{lastValue:6},b4:{lastValue:0}}
]
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js">
</script>
<div ng-app='app' ng-controller='ctrl'>
<input type='number' ng-model='filterStatus' ng-init='filterStatus=1'>
<ul>
<li ng-repeat='item in data | filter: {$:filterStatus}'>{{item.name}}</li>
</ul>
</div>

Filter for 3 levels, based on object.object.object.property with object.property

I'm trying to filter the object below by year._id and major._id:
student = {
_id: ,
name: ,
timetable: {
name: ,
_id: ,
academic_year: {
_id: ,
name:
},
major: {
_id: ,
name: ,
abbreviation_name:
}
}
}
I've tried like this:
<span ng-repeat="student in students |filter:{timetable: {academic_year: {_id: yearSearchIdKey}}} ></span>
and this
<span ng-repeat="student in students | filter:{timetable: [{academic_year: [{_id: yearSearchIdKey}]}]} ></span>
But neither one works.
How can I do it?
I suppose that you have an array, so you filter must be like this:
<span ng-repeat="student in students | filter: { student: { timetable: { academic_year: { _id: yearSearchIdKey }}}}" ng-bind="student | json"></span>
Working code:
(function() {
'use strict';
angular
.module('app', [])
.controller('MainCtrl', MainCtrl);
MainCtrl.$inject = ['$scope'];
function MainCtrl($scope) {
$scope.students = [{
"student": {
"_id": "studentId1",
"name": "student1",
"timetable": {
"name": "time1",
"_id": "timeId1",
"academic_year": {
"_id": "academic_yearId1",
"name": "academic_year1",
},
"major": {
"_id": "majorId1",
"name": "major1",
"abbreviation_name": "majorAbbr1"
}
}
}
}];
}
})();
<!doctype html>
<html ng-app="app">
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.7/angular.min.js"></script>
</head>
<body ng-controller="MainCtrl">
<input type="text" ng-model="yearSearchIdKey" placeholder="Search...">
<hr>
<pre ng-repeat="student in students | filter: { student: { timetable: { academic_year: { _id: yearSearchIdKey }}}}" ng-bind="student | json"></pre>
</body>
</html>

Angular Js Object Filter in ng-repeat

How can i filter based on object values like 1 or 2 or 3
i am trying to filter my json which looks similar to the names object
This is my code i tried to apply filter but its not working
<!DOCTYPE html>
<html>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<body>
<div ng-app="myApp" ng-controller="namesCtrl">
<ul>
<li ng-repeat="x in names ">
{{ x.name }}
</li>
</ul>
</div>
<script>
angular.module('myApp', []).controller('namesCtrl', function($scope) {
$scope.names = {
"1": {
"name": "some"
},
"2": {
"name": "values"
},
"3": {
"name": "are"
},
"4": {
"name": "there"
},
"5": {
"name": "here"
}
}
});
</script>
</body>
</html>
filter and orderBy do not work on object properties, only arrays. That being said, I think I found a solution that you will like:
<!DOCTYPE html>
<html>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<body>
<div ng-app="myApp" ng-controller="namesCtrl">
<input type="text" ng-model="searchText"/>
<ul ng-init="nameArray=objArray(names)">
<li ng-repeat="x in nameArray | filter:searchText">
{{x.value.name}}
</li>
</ul>
</div>
<script>
angular.module('myApp', []).controller('namesCtrl', function($scope) {
$scope.searchText='';
$scope.names = {
"1": {
"name": "some"
},
"2": {
"name": "values"
},
"3": {
"name": "are"
},
"4": {
"name": "there"
},
"5": {
"name": "here"
}
};
$scope.objArray=function (obj) {
var result=[];
for (var key in obj) {
result.push({
key: key,
value: obj[key]
});
}
return result;
}
});
</script>
</body>
</html>
I don't think you can filter on property names. I assume these property names are some kind of IDs that you want to filter on. Then your data structure should reflect that and be like this:
$scope.names = [
{ id: "1", name: "some" },
{ id: "2", name: "values" },
{ id: "3", name: "are" },
{ id: "4", name: "there" },
{ id: "5", name: "here" }
]
Then you can filter like this:
<ul>
<li ng-repeat="x in names | filter: { id: searchId } >
{{ x.name }}
</li>
</ul>
Replace the searchId with your specific scope variable which contains the ID you are looking for.

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.

Categories