I'm trying to customise this Angular Material example code (https://material.angularjs.org/latest/api/directive/mdSelect) to my needs.
I have three groups of select options. If an option is selected in a group, it should unselect all options in other groups (but leave other options in own group as they are).
In my code I have managed to get the logic working right (as you will see from the console.log outputs at the bottom), but the actual select options do not interact with user input.
My JSFiddle: https://jsfiddle.net/e2LLLxnb/8/
My JS code:
var myModule = angular.module('BlankApp', ['ngMaterial']);
myModule.controller("FilterCtrl", function($scope, $element) {
$scope.categories = ["Any", "Target Category", "Option 1", "Option 2", "Option 3", "Option 4"];
$scope.mustCatSelected;
$scope.categoryObj = {};
// build the list of options with values and groups - create equivalent of $scope.data for <md-option ng-repeat="item in categoryObj.data.items">
var finGroup = [];
$scope.categories.forEach(function(value,key){
if(key>1){
finGroup.push(key);
};
});
$scope.categoryObj.data = {items: [], groups: [{
group: [0]
}, {
group: [1]
}, {
group: finGroup
}]};
$scope.categories.forEach(function(value,key){
$scope.categoryObj.data.items.push({name: value,
value: false,
id: (key + 1)});
});
$scope.clickOn = function(item, index) {
if(item.value == false){item.value = item.name;}
else {item.value = false;}
if (item.value === false) {
} else {
var thisGroup = [];
angular.forEach($scope.categoryObj.data.groups, function(value, key) {
if (value.group.indexOf(index) !== -1) {
thisGroup = value.group;
}
});
angular.forEach($scope.categoryObj.data.items, function(value, key) {
if (thisGroup.indexOf(key) !== -1) {
return;
} else {
value.value = false;
}
});
$scope.mustCatSelected = $scope.categoryObj.data.items.filter(function(e){
return e.value != false;
});
console.log($scope.mustCatSelected);
console.log($scope.categoryObj.data.items);
}
}
//search-term header
$scope.searchTerm;
$scope.clearSearchTerm = function() {
$scope.searchTerm = '';
};
// The md-select directive eats keydown events for some quick select
// logic. Since we have a search input here, we don't need that logic.
$element.find('input').on('keydown', function(ev) {
ev.stopPropagation();
});
});
Solved (finally!): https://jsfiddle.net/hqck87t1/4/
var myModule = angular.module('BlankApp', ['ngMaterial']);
myModule.controller("FilterCtrl", function($scope, $element) {
$scope.categories = ["Any", "None", "Option 1", "Option 2", "Option 3", "Option 4"];
$scope.mustCatSelected = [];
$scope.categoryObj = {};
$scope.categoryObj.items = [];
$scope.categories.forEach(function(value,key){
var grp;
if (key < 2){grp = key;}
if (key >= 2){grp = 2;}
$scope.categoryObj.items.push({
name: value,
id: (key + 1),
group: grp});
});
//set default
$scope.mustCatSelected.push($scope.categoryObj.items[0]);
$scope.clickOn = clickOn;
function clickOn(newValue, oldValue, type) {
//console.log($scope.categoryObj.items);
//console.log(oldValue);
if(oldValue.length == 0) {
return false;
}
//create arrays of new and old option ids
oldValue = JSON.parse(oldValue);
var newIds = [];
var oldIds = [];
newValue.forEach(function(value,key){
newIds.push(value.id);
});
oldValue.forEach(function(value,key){
oldIds.push(value.id);
});
//define and set the clicked value
var clickedValue;
newIds.forEach(function(value, key){
if(oldIds.indexOf(value) == -1) {
clickedValue = value;
}
});
var clickedGroup;
newValue.forEach(function(value,key){
if(value.id == clickedValue){
clickedGroup = value.group;
}
});
//console.log([clickedValue, clickedGroup]);
//console.log([newIds, oldIds, clickedValue]);
if(type == 'mustCat'){
$scope.mustCatSelected = $scope.mustCatSelected.filter(function(e){
return e.group == clickedGroup;
});
}
}
//search term above select
$scope.searchTerm;
$scope.clearSearchTerm = function() {
$scope.searchTerm = '';
};
// The md-select directive eats keydown events for some quick select
// logic. Since we have a search input here, we don't need that logic.
$element.find('input').on('keydown', function(ev) {
ev.stopPropagation();
});
});
There key to the solution lies in two things:
Using ng-change instead of ng-click. The former is used to distinguish the state of ng-model inline vs the specified state of ng-model after the change event. Whereas ng-click is not reliable for this.
Write the ng-change function in the html like this:
ng-change="clickOn(mustCatSelected, '{{mustCatSelected}}')"
where mustCatSelected is the ng-model and '{{mustCatSelected}}' the inline state of ng-model before the change event.
Now we have an multiple md-select with logic handling the selection of options / groups of options.
I am developing an application where i popup a window and when it gets popup the next time i will try to open it should not be opened. Next time it should open When i will close the popup then it should open.
Now for that i am using count variable and whenever it will be 1 the popup opens and whenever it is greater than or equal to 2 it shows alert. But now when i close the popup it is not resetting the value of count to 0 in view.
In JSfiddle i tried using var self = this; it works fine but when i tried it on my code it says Uncaught Exception Typeerror cannot find property 'count' defined at line self.count = 0;
How to achieve this? or any alternate solution for this?
<a ui-sref-active="active" ng-click="count=count+1; connectMachine(machine, count)" ng-init="count=0" ><span><i class="fa fa-desktop fa-5x"></i></span></a>
$scope.connectMachine = function(machine, count) {
var promise = restAPIService.connectMachineService(
$scope.thisStudentThisBatch.guacProfileId,
machine.connectionId, $stateParams.batchID).get();
promise.$promise.then(function(response) {
var json = JSON.parse(response.data);
console.log(json.id);
var dnsUrl = $location.absUrl().split('/');
dnsUrl = dnsUrl[0] + '//' + dnsUrl[2];
var apiUrl = dnsUrl + $rootScope.apiUrl + "guacamole/disconnect/"
+ json.id;
var conn_params = $http.defaults.headers.common.Authorization
+ "++" + apiUrl;
$scope.machineURL = response.headers.url + "&conn_params="
+ conn_params;
var params = "height=" + screen.availHeight + ",width="
+ screen.availWidth;
var NewWin;
var self = this;
if ($scope.count == 1) {
NewWin = window.open($scope.machineURL);
} else if ($scope.count >= 2) {
alert("Back Off Back Off");
}
function checkWindow() {
if (NewWin && NewWin.closed) {
window.clearInterval(intervalID);
self.count = 0;
}
}
var intervalID = window.setInterval(checkWindow, 500);
}, function(error) {
dialogs.error("Error", error.data.error, {
'size' : 'sm'
});
});
}
You can use a variable defined on $scope to trigger the value of button instead of using ng-init
HTML:
<div ng-app="myApp">
<ul ng-controller="TodoCtrl">
<li class="list-group-item" ng-repeat="todo in todos">{{todo.text}}
<button class="btn btn-default" ng-click="addLike($index)">value- {{count[$index]}}</button>
</li>
</ul>
</div>
JS:
var myApp = angular.module('myApp', []);
function TodoCtrl($scope) {
$scope.todos = [{
text: 'todo one'
}, {
text: 'todo two',
done: false
}];
$scope.count = [0, 0];
$scope.addLike = function(index) {
var NewWin;
$scope.count[index] ++;
if ($scope.count[index] == 1) {
NewWin = window.open('https://www.google.com');
} else if ($scope.count >= 2) {
alert("Back Off Back Off");
}
function checkWindow() {
if (NewWin && NewWin.closed) {
window.clearInterval(intervalID);
$scope.count[index] = 0;
$scope.$apply();
}
}
var intervalID = window.setInterval(checkWindow, 500);
};
};
JS Fiddle :https://jsfiddle.net/p41dLjmn/
I want to use the filter in angular and want to filter for multiple values, if it has either one of the values then it should be displayed.
I have for example this structure:
An object movie which has the property genres and I want to filter for Action and Comedy.
I know I can do filter:({genres: 'Action'} || {genres: 'Comedy'}), but what to do if I want to filter it dynamically. E.g. filter: variableX
How do I set variableX in the $scope, when I have an array of the genres I have to filter?
I could construct it as a string and then do an eval() but I don't want to use eval()...
I would just create a custom filter. They are not that hard.
angular.module('myFilters', []).
filter('bygenre', function() {
return function(movies,genres) {
var out = [];
// Filter logic here, adding matches to the out var.
return out;
}
});
template:
<h1>Movies</h1>
<div ng-init="movies = [
{title:'Man on the Moon', genre:'action'},
{title:'Meet the Robinsons', genre:'family'},
{title:'Sphere', genre:'action'}
];" />
<input type="checkbox" ng-model="genrefilters.action" />Action
<br />
<input type="checkbox" ng-model="genrefilters.family" />Family
<br />{{genrefilters.action}}::{{genrefilters.family}}
<ul>
<li ng-repeat="movie in movies | bygenre:genrefilters">{{movie.title}}: {{movie.genre}}</li>
</ul>
Edit here is the link: Creating Angular Filters
UPDATE: Here is a fiddle that has an exact demo of my suggestion.
You can use a controller function to filter.
function MoviesCtrl($scope) {
$scope.movies = [{name:'Shrek', genre:'Comedy'},
{name:'Die Hard', genre:'Action'},
{name:'The Godfather', genre:'Drama'}];
$scope.selectedGenres = ['Action','Drama'];
$scope.filterByGenres = function(movie) {
return ($scope.selectedGenres.indexOf(movie.genre) !== -1);
};
}
HTML:
<div ng-controller="MoviesCtrl">
<ul>
<li ng-repeat="movie in movies | filter:filterByGenres">
{{ movie.name }} {{ movie.genre }}
</li>
</ul>
</div>
Creating a custom filter might be overkill here, you can just pass in a custom comparator, if you have the multiples values like:
$scope.selectedGenres = "Action, Drama";
$scope.containsComparator = function(expected, actual){
return actual.indexOf(expected) > -1;
};
then in the filter:
filter:{name:selectedGenres}:containsComparator
Here is the implementation of custom filter, which will filter the data using array of values.It will support multiple key object with both array and single value of keys. As mentioned inangularJS API AngularJS filter Doc supports multiple key filter with single value, but below custom filter will support same feature as angularJS and also supports array of values and combination of both array and single value of keys.Please find the code snippet below,
myApp.filter('filterMultiple',['$filter',function ($filter) {
return function (items, keyObj) {
var filterObj = {
data:items,
filteredData:[],
applyFilter : function(obj,key){
var fData = [];
if (this.filteredData.length == 0)
this.filteredData = this.data;
if (obj){
var fObj = {};
if (!angular.isArray(obj)){
fObj[key] = obj;
fData = fData.concat($filter('filter')(this.filteredData,fObj));
} else if (angular.isArray(obj)){
if (obj.length > 0){
for (var i=0;i<obj.length;i++){
if (angular.isDefined(obj[i])){
fObj[key] = obj[i];
fData = fData.concat($filter('filter')(this.filteredData,fObj));
}
}
}
}
if (fData.length > 0){
this.filteredData = fData;
}
}
}
};
if (keyObj){
angular.forEach(keyObj,function(obj,key){
filterObj.applyFilter(obj,key);
});
}
return filterObj.filteredData;
}
}]);
Usage:
arrayOfObjectswithKeys | filterMultiple:{key1:['value1','value2','value3',...etc],key2:'value4',key3:[value5,value6,...etc]}
Here is a fiddle example with implementation of above "filterMutiple" custom filter.
:::Fiddle Example:::
If you want to filter on Array of Objects then you can give
filter:({genres: 'Action', key :value }.
Individual property will be filtered by particular filter given for that property.
But if you wanted to something like filter by individual Property and filter globally for all properties then you can do something like this.
<tr ng-repeat="supp in $data | filter : filterObject | filter : search">
Where "filterObject" is an object for searching an individual property and "Search" will search in every property globally.
~Atul
I've spent some time on it and thanks to #chrismarx, I saw that angular's default filterFilter allows you to pass your own comparator. Here's the edited comparator for multiple values:
function hasCustomToString(obj) {
return angular.isFunction(obj.toString) && obj.toString !== Object.prototype.toString;
}
var comparator = function (actual, expected) {
if (angular.isUndefined(actual)) {
// No substring matching against `undefined`
return false;
}
if ((actual === null) || (expected === null)) {
// No substring matching against `null`; only match against `null`
return actual === expected;
}
// I edited this to check if not array
if ((angular.isObject(expected) && !angular.isArray(expected)) || (angular.isObject(actual) && !hasCustomToString(actual))) {
// Should not compare primitives against objects, unless they have custom `toString` method
return false;
}
// This is where magic happens
actual = angular.lowercase('' + actual);
if (angular.isArray(expected)) {
var match = false;
expected.forEach(function (e) {
e = angular.lowercase('' + e);
if (actual.indexOf(e) !== -1) {
match = true;
}
});
return match;
} else {
expected = angular.lowercase('' + expected);
return actual.indexOf(expected) !== -1;
}
};
And if we want to make a custom filter for DRY:
angular.module('myApp')
.filter('filterWithOr', function ($filter) {
var comparator = function (actual, expected) {
if (angular.isUndefined(actual)) {
// No substring matching against `undefined`
return false;
}
if ((actual === null) || (expected === null)) {
// No substring matching against `null`; only match against `null`
return actual === expected;
}
if ((angular.isObject(expected) && !angular.isArray(expected)) || (angular.isObject(actual) && !hasCustomToString(actual))) {
// Should not compare primitives against objects, unless they have custom `toString` method
return false;
}
console.log('ACTUAL EXPECTED')
console.log(actual)
console.log(expected)
actual = angular.lowercase('' + actual);
if (angular.isArray(expected)) {
var match = false;
expected.forEach(function (e) {
console.log('forEach')
console.log(e)
e = angular.lowercase('' + e);
if (actual.indexOf(e) !== -1) {
match = true;
}
});
return match;
} else {
expected = angular.lowercase('' + expected);
return actual.indexOf(expected) !== -1;
}
};
return function (array, expression) {
return $filter('filter')(array, expression, comparator);
};
});
And then we can use it anywhere we want:
$scope.list=[
{name:'Jack Bauer'},
{name:'Chuck Norris'},
{name:'Superman'},
{name:'Batman'},
{name:'Spiderman'},
{name:'Hulk'}
];
<ul>
<li ng-repeat="item in list | filterWithOr:{name:['Jack','Chuck']}">
{{item.name}}
</li>
</ul>
Finally here's a plunkr.
Note: Expected array should only contain simple objects like String, Number etc.
you can use searchField filter of angular.filter
JS:
$scope.users = [
{ first_name: 'Sharon', last_name: 'Melendez' },
{ first_name: 'Edmundo', last_name: 'Hepler' },
{ first_name: 'Marsha', last_name: 'Letourneau' }
];
HTML:
<input ng-model="search" placeholder="search by full name"/>
<th ng-repeat="user in users | searchField: 'first_name': 'last_name' | filter: search">
{{ user.first_name }} {{ user.last_name }}
</th>
<!-- so now you can search by full name -->
You can also use ngIf if the situation permits:
<div ng-repeat="p in [
{ name: 'Justin' },
{ name: 'Jimi' },
{ name: 'Bob' }
]" ng-if="['Jimi', 'Bob'].indexOf(e.name) > -1">
{{ p.name }} is cool
</div>
The quickest solution that I've found is to use the filterBy filter from angular-filter, for example:
<input type="text" placeholder="Search by name or genre" ng-model="ctrl.search"/>
<ul>
<li ng-repeat="movie in ctrl.movies | filterBy: ['name', 'genre']: ctrl.search">
{{movie.name}} ({{movie.genre}}) - {{movie.rating}}
</li>
</ul>
The upside is that angular-filter is a fairly popular library (~2.6k stars on GitHub) which is still actively developed and maintained, so it should be fine to add it to your project as a dependency.
I believe this is what you're looking for:
<div>{{ (collection | fitler1:args) + (collection | filter2:args) }}</div>
Please try this
var m = angular.module('yourModuleName');
m.filter('advancefilter', ['$filter', function($filter){
return function(data, text){
var textArr = text.split(' ');
angular.forEach(textArr, function(test){
if(test){
data = $filter('filter')(data, test);
}
});
return data;
}
}]);
Lets assume you have two array, one for movie and one for genre
Just use the filter as: filter:{genres: genres.type}
Here genres being the array and type has value for genre
I wrote this for strings AND functionality (I know it's not the question but I searched for it and got here), maybe it can be expanded.
String.prototype.contains = function(str) {
return this.indexOf(str) != -1;
};
String.prototype.containsAll = function(strArray) {
for (var i = 0; i < strArray.length; i++) {
if (!this.contains(strArray[i])) {
return false;
}
}
return true;
}
app.filter('filterMultiple', function() {
return function(items, filterDict) {
return items.filter(function(item) {
for (filterKey in filterDict) {
if (filterDict[filterKey] instanceof Array) {
if (!item[filterKey].containsAll(filterDict[filterKey])) {
return false;
}
} else {
if (!item[filterKey].contains(filterDict[filterKey])) {
return false;
}
}
}
return true;
});
};
});
Usage:
<li ng-repeat="x in array | filterMultiple:{key1: value1, key2:[value21, value22]}">{{x.name}}</li>
Angular Or Filter Module
$filter('orFilter')([{..}, {..} ...], {arg1, arg2, ...}, false)
here is the link: https://github.com/webyonet/angular-or-filter
I had similar situation. Writing custom filter worked for me. Hope this helps!
JS:
App.filter('searchMovies', function() {
return function (items, letter) {
var resulsts = [];
var itemMatch = new RegExp(letter, 'i');
for (var i = 0; i < items.length; i++) {
var item = items[i];
if ( itemMatch.test(item.name) || itemMatch.test(item.genre)) {
results.push(item);
}
}
return results;
};
});
HTML:
<div ng-controller="MoviesCtrl">
<ul>
<li ng-repeat="movie in movies | searchMovies:filterByGenres">
{{ movie.name }} {{ movie.genre }}
</li>
</ul>
</div>
Here is my example how create filter and directive for table jsfiddle
directive get list (datas) and create table with filters
<div ng-app="autoDrops" ng-controller="HomeController">
<div class="row">
<div class="col-md-12">
<h1>{{title}}</h1>
<ng-Multiselect array-List="datas"></ng-Multiselect>
</div>
</div>
</div>
my pleasure if i help you
Too late to join the party but may be it can help someone:
We can do it in two step, first filter by first property and then concatenate by second filter:
$scope.filterd = $filter('filter')($scope.empList, { dept: "account" });
$scope.filterd = $scope.filterd.concat($filter('filter')($scope.empList, { dept: "sales" }));
See the working fiddle with multiple property filter
OPTION 1:
Using Angular providered filter comparator parameter
// declaring a comparator method
$scope.filterBy = function(actual, expected) {
return _.contains(expected, actual); // uses underscore library contains method
};
var employees = [{name: 'a'}, {name: 'b'}, {name: 'c'}, {name: 'd'}];
// filter employees with name matching with either 'a' or 'c'
var filteredEmployees = $filter('filter')(employees, {name: ['a','c']}, $scope.filterBy);
OPTION 2:
Using Angular providered filter negation
var employees = [{name: 'a'}, {name: 'b'}, {name: 'c'}, {name: 'd'}];
// filter employees with name matching with either 'a' or 'c'
var filteredEmployees = $filter('filter')($filter('filter')(employees, {name: '!d'}), {name: '!b'});
My solution
ng-repeat="movie in movies | filter: {'Action'} + filter: {'Comedy}"
the best answer is :
filter:({genres: 'Action', genres: 'Comedy'}
I've been facing an issue since couple of hours. My view template looks like-
<div class="row" ng-repeat="row in CampaignsService.getRows().subItems track by $index">
<div class="col-sm-2">
<select class="form-control dropDownPercent" ng-model="CampaignsService.dropDownPercent[{{CampaignsService.selectCounter}}]" ng-change="CampaignsService.wow(CampaignsService.dropDownPercent, $index)" ng-options="o as o for o in CampaignsService.showPercentDropDown().values">
</select>
</div>
<div class="col-sm-2" style="line-height: 32px">
of visitors send to
</div>
<div class="col-sm-4">
<select class="form-control" ng-model="campaignSelect" ng-options="campaign.Campaign.id as campaign.Campaign.title for campaign in CampaignsService.getRows().items">
<option value=""> Please select </option>
</select>
</div>
<div class="col-sm-4">
<a class="btn btn-default" target="_blank" href="">Show campaign</a>
</div>
Variable CampaignsService.selectCounter is a counter variable and declared in service but when I'm going to use ng-model="CampaignsService.dropDownPercent[{{CampaignsService.selectCounter}}]" it gives me error -
Error: [$parse:syntax] Syntax Error: Token '{' invalid key at column 35 of the expression [CampaignsService.dropDownPercent[{{CampaignsService.selectCounter}}]] starting at [{CampaignsService.selectCounter}}]]
And when I use ng-model="CampaignsService.dropDownPercent['{{CampaignsService.selectCounter}}']" it does not give any error but it takes this variable as string.
My question is how could I create a model array and get model's array values in my service ?? I read many questions in stack community and none of the trick work for me. My service under my script, is
.service('CampaignsService', ['$rootScope', 'AjaxRequests', function ($rootScope, AjaxRequests) {
this.dropDownPercent = [];
this.selectCounter = 0;
var gareeb = [];
this.showPercentDefault = 100;
// this.campaignsData = [];
this.$rowsData = {
items: [], //array of objects
current: [], //array of objects
subItems: [] //array of objects
};
this.getRows = function () {
return this.$rowsData;
}
this.addNewRow = function () {
var wowRow = {}; //add a new object
this.getRows().subItems.push(wowRow);
this.selectCounter++;
gareeb.push(0);
}
this.calculatePercentages = function (index) {
angular.forEach(this.getRows().current, function (data, key) {
if (key == index) {
console.log(data);
}
})
}
this.showPercentDropDown = function ($index) {
var balle = 0;
var start;
angular.forEach(gareeb, function (aha, keywa) {
balle += aha;
})
var last = 100 - balle;
var final = [];
for (start = 0; start <= last; start += 10) {
final.push(start);
}
return this.values = {
values: final,
};
}
this.wow = function (valueWa, keyWa) {
console.log(this.dropDownPercent);
gareeb[keyWa] = valueWa;
this.changePercentDropDown();
}
this.changePercentDropDown = function () {
var angElement = angular.element(document.querySelector('.dropDownPercent'));
angular.forEach(angElement, function (data, key) {
console.log(data);
})
}
}])
Target model structure should be
ng-model="CampaignsService.dropDownPercent[1]"
ng-model="CampaignsService.dropDownPercent[2]"
ng-model="CampaignsService.dropDownPercent[3]"
A big thanks in advance.
Since you are in context of the Angular expression, you don't need interpolation tags {{...}}. So ngModel directive should look like this:
ng-model="CampaignsService.dropDownPercent[CampaignsService.selectCounter]"
I'm trying to apply a check box filter to a list, but the options for the check boxes should also be come the list of items only,
it works fine if i am iterating it for all the check boxes,
the problem is coming when i am trying to apply the unique filter to display check boxes options.
i have included
angular 1.4 and ui-utils
<script src="js/angular.min.js"></script>
<script src="js/ui-utils.min.js"></script>
my view and controller are defined as:
<div ng-controller="Test">
<div ng-repeat="person in persons | unique:type">
<!-- record that this person has been selected -->
<input type="checkbox" ng-checked="person.checked" ng-model="person.checked" /> {{ person.type }}
</div>
<ul>
<li ng-repeat="person in persons | selectedTypes">{{person.name}}</li>
</ul>
</div>
and script is
<script>
var app = angular.module("MyApp", ['ui.utils']);
app.controller("Test", function($scope) {
$scope.persons = [
{ type: 1, name: 'Ankit Balyan' },
{ type: 1, name: 'Abhilaksh' },
{ type: 2, name: 'Sanket Srivastav' },
{ type: 2, name: 'Sachin Sharma' },
{ type: 2, name: 'Rohan Rathor' },
{ type: 2, name: 'Jim' },
];
$scope.$watch('persons', function() {
console.log($scope.persons);
})
});
// Define our filter
app.filter('selectedTypes', function($filter) {
return function(persons) {
var i, len;
// get persons that have been checked
var checkedPersons = $filter('filter')(persons, {checked: true});
// Add in a check to see if any persons were selected. If none, return
// them all without filters
if(checkedPersons.length == 0) {
return persons;
}
//console.log(checkedPersons);
// get all the unique cities that come from these checked persons
var types = {};
for(i = 0, len = checkedPersons.length; i < len; ++i) {
// if this checked persons cities isn't already in the cities object
// add it
if(!types.hasOwnProperty(checkedPersons[i].type)) {
types[checkedPersons[i].type] = true;
}
}
// Now that we have the cities that come from the checked persons, we can
//get all persons from those cities and return them
var ret = [];
for(i = 0, len = persons.length; i < len; ++i) {
// If this person's city exists in the cities object, add it to the
// return array
if(types[persons[i].type]) {
ret.push(persons[i]);
}
}
//console.log(persons.length);
// we have our result!
return ret;
};
});
</script>
You have to put the name of the property as a string :
<div ng-repeat="person in persons | unique: 'type'">
instead of
<div ng-repeat="person in persons | unique: type">
Edit: If you don't provide quotes, you are applying a unique filter by the value of the variable type, which is not defined in your case, therefore the filter has no effect.