Angular UI-Bootstrap Multiple Checkboxes Filter - angularjs

I want to filter my data with multiple checkboxes. One variable can have multiple filters.
Here is the link
So for example when 4 and 5 are checked, all 4s and 5s are shwon.
html:
<div class="btn-group" data-toggle="buttons-checkbox">
<pre>{{checkboxes}}</pre>
<companies ng-repeat="check in checkboxes">
<button type="button" class="btn" ng-model="check.truth"
btn-checkbox-true="check.value" btn-checkbox>{{check.value}}</button>
</companies>
</div>
and js:
$scope.checkboxes = [{"value":"1","truth":false},{"value":"2","truth":false}, {"value":"3","truth":false},{"value":"4","truth":false}];
$scope.data = [{"name":"Some Name","value":"1"},{"name":"Another Name","value":"2"},{"name":"Cool Name","value":"3"},{"name":"Funky Name","value":"4"}]

You can create a custom filter
<tr ng-repeat="d in data | myfilter:checkboxes">
app.filter('myfilter', function () {
return function (data, values) {
var vs = [];
angular.forEach(values, function (item) {
if ( !! item.truth) {
vs.push(item.value);
}
});
if (vs.length === 0) return data;
var result = [];
angular.forEach(data, function (item) {
if (vs.indexOf(item.value) >= 0) {
result.push(item);
}
});
return result;
}
});
Working Demo

Related

Calling $scope in custom filter (angular)

I'm using this angular filter to filter out objects in an array whose localteam_id properties match a value that is held in $scope.whichMyteam. This works fine.
VIEW
<div ng-repeat="fixture in getFixtures | filter: {localteam_id: whichMyteam} ">
I want to extend the filter however, to include a section criterion: so it will, in effect, be:
<div ng-repeat="fixture in getFixtures | filter: {localteam_id: whichMyteam && visitorteam_id: whichMyteam} ">
...but a) this doesn't work, and b) even if it did, it's getting a little cumbersome and seems that it would justify making a custom filter.
So, I tried to make one. The problem I ran into is I need to reference the $scope.whichMyteam value in the filter, but it seems the filter module can't accept/understand $scope. This is crucial for the filter to work in my instance, so I'm not sure how to resolve this.
My filter so far looks like this:
app.filter('myFixtures', function() {
return function(input) {
angular.forEach(input, function(o) {
output = [];
if (o.localteam_id === $scope.whichMyteam) {
output.push(o);
}
return output;
})
};
});
The above is a simplified version which only attempts to match one property (just did this to test it and reduce the number of moving parts). When I call it in the view though...
<div ng-repeat="fixture in getFixtures | myFixtures">
...it doesn't work. Console logs '$scope is not defined'.
UPDATE: I tried this, still not working!
FILTER
var myFilters = angular.module('myFilters', [])
myFilters.filter('myFixtures', function(whichMyteam) {
return function(input) {
angular.forEach(input, function(o) {
output = [];
if (o.localteam_id === whichMyteam) {
output.push(o);
}
return output;
})
}
});
VIEW
<div ng-repeat="fixture in getFixtures | myFixtures(whichMyteam)">
Console is logging a syntax error (I think...)
angular.js:13236 Error: [$parse:syntax]
How about having your filter function return a function.
app.filter('myFixtures', function() {
return function(input, whichMyteam) {
output = [];
angular.forEach(input, function(o) {
if (o.localteam_id === whichMyteam) {
output.push(o);
}
})
return output;
};
});
Then call the filter function passing in your variable
<div ng-repeat='fixture in getFixtures | myFixtures:whichMyteam'>
--- example
angular
.module('app', [])
.filter('otherFilter', otherFilter)
.controller('controller', controller);
controller.$inject = ['$scope'];
function controller($scope) {
$scope.things = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
$scope.modVal = 2;
console.log('controller');
$scope.myFilter = function(x) {
return function(y) {
return (y % x) === 0;
}
};
}
function otherFilter() {
return function(y, x) {
var out = [];
angular.forEach(y, function(val) {
if ((val % x) === 0) {
out.push(val)
}
});
return out;
}
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app='app' ng-controller='controller'>
<div ng-repeat='thing in things | filter:myFilter(modVal)'>
{{ thing }}
</div>
<br/>
<div ng-repeat='thing in things | otherFilter:modVal'>
{{ thing }}
</div>
</div>
You have 2 problems here:
1. How to pass a param, html:
<div ng-repeat="fixture in getFixtures | myFixtures:whichMyteam">
js:
myFilters.filter('myFixtures', function() {
return function(input, whichMyteam) {
...
Do not place return statement inside forEach -- it does not make what you think;)
So finally your filter is:
myFilters.filter('myFixtures', function() {
return function(input, whichMyteam) {
output = [];
angular.forEach(input, function(o) {
if (o.localteam_id === whichMyteam) {
output.push(o);
}
})
return output;
}
});
http://plnkr.co/edit/0XFfI8hIdCaJ19gJRYr2?p=preview

How to find an array object according to given information?

I have an array in AngularJS controller like this:
$scope.persons = [{name:'Joey', age:'27'},{name:'Lucy', age:'22'}]
I have got a name 'Lucy', how can I get the age of the name in the controller (not in HTML)?
I've created a plunk here that outlines a single result, with just the age, as well as multiple results.
This could also be implemented within a filter, which is documented on the Angular site here: https://docs.angularjs.org/api/ng/filter/filter
https://plnkr.co/edit/OFRMzpQrZfTOnaFyJP7Z?p=info
angular.module('plnk',[]).controller('plnkCtrl', function($scope){
// Note, I added a second Joey here to test the multiple function.
// For output, check the browser console.
$scope.persons = [{name:'Joey', age:'27'},{name:'Joey', age:'28'},{name:'Lucy', age:'22'}]
console.log('Single -> ', getAgeSingle('Lucy'));
console.log('Multiple ->',getAgeMultiple('Joey'));
function getAgeMultiple(personLookup) {
var results = [];
angular.forEach($scope.persons,function(person){
if (person.name === personLookup) {
results.push(person);
// or results.push(person.age) for age only
}
});
return results;
}
function getAgeSingle(personLookup) {
var result = '';
angular.forEach($scope.persons,function(person){
if (person.name === personLookup && !result) {
result = person.age;
}
});
return result;
}
});
Just loop over the array and check, like this:
function getAge(name)
{
for (var i = 0; i < $scope.persons.length; i++)
{
var person = $scope.persons[i];
if (person.name === name)
{
return parseInt(person.age, 10);
}
}
return undefined;
}
This has a couple caveats -- if you have dupes you'll only get the first one and it runs in linear time. If you control the data source it'd be better to use a JS object/hashmap/dictionary/whatever you want to call it.
If you wanted to loop through the scope:
$scope.persons = [{name:'Joey', age:'27'}, {name:'Lucy', age:'22'}]
function getAge(name) {
angular.forEach($scope.persons, function (value, index) {
if (value.name === name) {
return parseInt(value.age, 10);
}
});
return undefined;
}
The HTML way:
<div ng-app="myApp" ng-controller="MainCtrl">
<table>
<tr ng-repeat="person in persons">
<td>Name: {{person.name}} Age: {{person.age}}</td>
</tr>
</table>
</div>
JS:
var app = angular.module('myApp', []);
app.controller('MainCtrl', function ($scope) {
$scope.persons = [{name:'Joey', age:'27'}, {name:'Lucy', age:'22'}];
});

Get ng-model in ng-repeat in ng-repeat with Protractor

How can I get the ng-model in ng-repeat in ng-repeat with protractor ?
<div ng-repeat="field in master.linker | orderBy:'country.name'">
<div>
<p> {{ field.country_name }} </p>
<label ng-repeat="user in user_list">
<input type="checkbox" ng-model="selected_user">
<span ng-bind="user.name"></span>
</label>
</div>
</div>
I use filter() to check my ng-repeat :
var fields = element.all(by.repeater('field in master.linker'));
fields.filter(function (field) {
return field.element(by.binding("field.country_name")).getText().then(function (country) {
return country === "en";
});
}).then(function (filteredFields) {
var fields2 = filteredFields[0].element.all(by.repeater('user in user_list'));
return fields2.filter(function (field2) {
return field2.element(by.binding('user.name')).getText().then(function (value) {
return value === user;
});
}).then(function (filteredFields) {
var myuser = filteredFields[0].element(by.model('user_name'));
self.current_step.expect(input.getAttribute('value')).to.eventually.equal('');
});
});;
I have this error in my console :
TypeError: filteredFields[0].element.all is not a function
Use .all() instead of .element.all():
filteredFields[0].all(by.repeater('user in user_list'));
You can also simplify things using first():
var fields = element.all(by.repeater('field in master.linker'));
var filteredUser = fields.filter(function (field) {
return field.element(by.binding("field.country_name")).getText().then(function (country) {
return country === "en";
});
}).first().all(by.repeater('user in user_list')).filter(function (userField) {
return userField.element(by.binding('user.name')).getText().then(function (value) {
return value === user;
});
}).first();
var myuser = filteredUser.element(by.model('user_name'));
self.current_step.expect(myuser.getAttribute('value')).to.eventually.equal('');
You may also look into the column() and row() repeater API.

how to move filter outside of controller in angular

I'm new in angular . i managed to filter using angular and it work fine but now i want to move filter outside of the controller which is quite challenging for me .
here is my html page :
<div >
<input type="checkbox" ng-click="itemType('CAR')"/> CAR
<input type="checkbox" ng-click="itemType('BIKE')"/> BIKE
<input type="checkbox" ng-click="itemType('CYCLE')"/> CYCLE
</div>
<table>
<tbody>
<tr ng-repeat="item in items | filter:filterItem">
<td >{{item.name}}</td>
<td >{{item.type}}</td>
</tr>
</tbody>
</table>
and controller :
app.controller('MainCtrl', function($scope) {
$scope.items = [
{name: 'bmw', type:'CAR' },
{name: 'ducati',type:'BIKE'},
{name: 'airbas',type:'CYCLE' }
];
$scope.typeArray = [];
$scope.itemType = function(type) {
var i = $.inArray(type, $scope.typeArray);
if (i > -1) {
$scope.typeArray.splice(i, 1);
} else {
$scope.typeArray.push(type);
}
}
$scope.filterItem = function(item) {
if ($scope.typeArray.length > 0) {
if ($.inArray(item.type, $scope.typeArray) < 0){
return false;
}
}
return item;
}
});
how can i move filtering from controller to app.filter().
Thanks.
Yes, the custom filter is a separate module and you can write it as:
iApp.filter('myfilter', function() {
return function( items, types) {
var filtered = [];
var looping = function(name){
angular.forEach(items, function(item) {
if(item.type === name){
filtered.push(item);
}
});
}
if(types.car == true){
looping('CAR');
}
if(types.bike == true){
looping('BIKE');
}
if(types.cycle == true){
looping('CYCLE');
}
return filtered;
};
});
Controller:
$scope.types = {car: false, bike:false, cycle: false};
$scope.items = [
{name: 'bmw', type:'CAR' },
{name: 'ducati',type:'BIKE'},
{name: 'airbas',type:'CYCLE' }
];
Demo 1 Plunker
[EDIT]
If you want to show all cells when no checkbox is selected, add this to filter:
var flag = true;
angular.forEach(types, function(type){
flag = flag & !type; // if one of flags will be false, we get flag=false
});
if(flag == true){
return items;
}
Demo 2 Plunker
FYI: You can see that filters do not use $scope. If you want to pass additional argument the syntax should be:
<tr ng-repeat="item in items | filter:myfilter:types">
where types is some object

Chaining Angular filters in controller while making them variable

Say I create an Angular app and write some new filters: Show only odds, and show only lucky numbers.
There's an oddList filter and a luckyList filter:
var app = angular.module('app', []);
app.filter('oddList', function() {
return function(items) {
var filtered = [];
angular.forEach(items, function(item) {
if (item % 2 !== 0)
filtered.push(item);
});
return filtered;
};
});
app.filter('luckyList', function() {
return function(items) {
var filtered = [];
angular.forEach(items, function(item) {
if (item === 2 || item === 7 || item === 11)
filtered.push(item);
});
return filtered;
};
});
In the view portion, I can chain these filters:
<ul><li ng-repeat="number in numbers | oddList | luckyList">{$number}</li></ul>
When this works, I should see 7 and 11 remaining.
I want to make my filters variable for this ng-repeat. Is there something I can do that's similar to this process?
Say I name the variable filter filter:listFilter so that in our controller, we can dynamically update $scope.listFilter.
<ul><li ng-repeat="number in numbers | filter:listFilter">{$number}</li></ul>
And the controller with pseudo code:
app.controller('main', function($scope, $filter) {
$scope.numbers = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15];
$scope.listFilter = $filter('oddList | luckyList');
});
Any idea how I could chain (variable) filters in the controller? Would like to be able to toggle between just odd, just lucky and/or both.
An approach is to use a function to return the filtered data:
function MainCtrl($scope, $filter) {
$scope.numbers = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15];
$scope.filteredNumbers = function() {
var result = $scope.numbers;
if ($scope.oddListEnabled) {
result = $filter('oddList')(result);
}
if ($scope.luckyListEnabled) {
result = $filter('luckyList')(result);
}
return result;
};
}
And the template:
<ul>
<li ng-repeat="number in filteredNumbers()">
{{number}}
</li>
</ul>
Here is a plunkr: http://plnkr.co/edit/4ectDA?p=preview

Resources