angularJS filter expression in ng-repeat - javascript

I would like to know what is the most elegant and simple way to implement this.
I need to add a filter expression for a ng-repeat that would filter 2 conditions from one property.
In this example http://plnkr.co/edit/OMQxXvSjtuudMRGE4eZ8?p=preview
If you enter A, it would display checkbox for A,
enter B - display checkbox for B.
But I want to display the specified checkboxes plus anything with empty condition.
There is no condition for C, so:
if you enter A, I want to display both A and C checkboxes,
enter B, I want to display both B and C checkboxes.

I would create custom filter like:
app.filter('myfilter', function() {
return function( items, condition) {
var filtered = [];
if(condition === undefined || condition === ''){
return items;
}
angular.forEach(items, function(item) {
if(condition === item.condition || item.condition === ''){
filtered.push(item);
}
});
return filtered;
};
});
and usage:
<span ng-repeat="charge in charges | myfilter:level.condition">
See Demo in Plunker
It looks pretty elegant and clear.
Hope it will help

I think you can do this pretty easily with just a filter expression function on your scope like this;
$scope.filterExpression = function(charge) {
return (!$scope.level || !charge.condition ||
($scope.level.condition.toUpperCase() === charge.condition.toUpperCase()));
}
and call it like this;
<span ng-repeat="charge in charges | filter:filterExpression">
plunkr (corrected)

you can use :
data-ng-repeat="charge in charges | filter:searchText" data-ng-if="filter = searchText.Name"

Use two ng-repeats, one after another:
1st : Filter on anything that has checkbox checked AND has a condition
2nd : Filter on things that don't have conditions

Related

angularjs : filter array with unsaved changes by name using an input tag

I normally filter an array using input tag like this :
$scope.filtername = function (vname) {
//repopulate the array from a copy every time input changes
$scope.items = $scope.items_filter;
//filter array if vname is a substring from item.name
if (vname && vname.trim() != '') {
$scope.items = $scope.items.filter((item) => {
return (item.name.toLowerCase().indexOf(vname.toLowerCase()) > -1);
})
}
};
<input type="search" ng-model="namev" ng-change="filtername(namev)">
But since the user needs to filter the array while editing hundreds of items with unsaved changes, I'm not sure how to proceed. Should I use ng-show instead ? or is there a better vanilla javascript way?
do you have a better way to filter array using a search input?
One approach is to create a custom filter:
app.filter("myFilter", function() {
return function(inputArr,vname) {
//repopulate the array from a copy every time input changes
var result = inputArr.concat();
//filter array if vname is a substring from item.name
if (vname && vname.trim() != '') {
result = result.filter((item) => {
return (item.name.toLowerCase().indexOf(vname.toLowerCase()) > -1);
});
};
return result;
};
})
Usage:
<input type="text" ng-model="namev" />
<div ng-repeat="item in items | myFilter : namev">
{{item.name}} {{item.contents}}
</div>
For more information, see AngularJS Developer Guide - Creating Custom Filters
can you explain the purpose of inputArr ?
The first argument to the filter function is the array to be filtered. This way it can be used with other scope variables:
<div ng-repeat="item in items | myFilter : namev">
{{item.name}} {{item.contents}}
</div>
<div ng-repeat="o in otherItems | myFilter : namev">
{{o.name}} {{o.contents}}
</div>
When AngularJS pipes data to a filter, it invokes the filter function with the data as the first argument. Subsequent arguments come from expressions separated by colons (:).
For more information, see AngularJS Developer Guide - Using filters in view templates

use array in custom filter

I created an array that has the following format...
$scope.myArr = [arg1, arg2];
Now I want to create a custom filter that will take the array as a parameter and compare to another array, for example I want to use it as so...
<div class="form-container" ng-repeat="formblock in forms | filter:dateFilter(myArr)">
This way every formblock will be compared to the array, so if formblock.date has either arg1 or arg2 then these will show, otherwise hide everything else.
Is this possible?
Your html with custom Angular#Filter should be
<div class="form-container" ng-repeat="formblock in forms | dateFilter:myArr">
Your forms is passed as firsr parameter implicitely and passed the additional parameter with : after filter name.
JS :
Filter :
app.filter('dateFilter', function() {
var boolFound = false;
return function(arrForm, arrArg) {
arrForm.forEach(function(val, key) {
var boolFound = false;
arrArg.forEach(function(val1, key1) {
if (val.date === val1) {
boolFound = true;
}
});
if (boolFound === false) {
arrForm.splice(key, 1);
}
});
return arrForm;
}
})
Here is the updated Fiddle

Filter ng-repeat by status

I have a dropdown with values in it. They're accessed through the .value property. I have an ng-repeat on a div that is repeating a lot of data. That data has statuses. When a user selects to filter by a status in the dropdown, I want to filter the ng-repeat by whatever status they chose and the status in the ng-repeat. Here's a better example of what I mean:
data-ng-repeat="stackoverflow in overflows| filter:stackoverflow.property.status===status.value"
In my case, I need to access stackoverflow.property.status and compare it to whatever status is in the drop down.
You'll want to do something like the following:
<span ng-repeat="stackoverflow in overflows | filter: { status : selectedStatus }"></span>
selectedStatus will be the value of ng-model on your dropdown.
You could have something like this
ng-repeat="stackoverflow in overflows | filter: { locations: [{ status: status.value }] }"
Under the circumstances, it ended up just being easier to write my own function and filter by it. In this case, I have a function search that I pass to filter. Works great for me.
I followed an answer that I found on another question. You can view it here: http://jsfiddle.net/suCWn/
$scope.search = function (shop) {
if ($scope.selectedCityId === undefined || $scope.selectedCityId.length === 0) {
return true;
}
var found = false;
angular.forEach(shop.locations, function (location) {
if (location.city_id === parseInt($scope.selectedCityId)) {
found = true;
}
});
return found;
};`
Here's the question: Angularjs filter nested object

How to create dynamic if-conditions

I want to make a dynamic filter method, but don't know how to include conditions dynamically.
Example
var do_test_1 = true,
do_test_2 = false,
do_test_3 = true;
Now there are three tests:
if (foo == bar) // test 1
if (john == doe) // test 2
if (jane == doe) // test 3
Now I want to build a dynamic if clause, based on the do_test vars.
Real use case
I have a list of tasks and want to filter them:
If the "assigned to me" filter is active, it should return only the the tasks that are assigned to me.
If the "high priority" filter and the "assigned to me" filter is active, it should return only the tasks that are assigned to me and have a high priority.
... and so on ...
I played around with the filter method, but I only get it working with an OR logic (show tasks that are assigned to me or have a high priority):
var $show = $tasks.filter(function(index, task) {
var $task = $(task);
return ((task.data('assigned') && filters['mytasks']) || (task.data('priority') == 3 && filters['priority']))
});
use eval() function
for(var i=0;i<3;i++){
var f=i+1;
eval("if(f==i+1){alert(i);}");
}
Demo: http://jsfiddle.net/ke42b/2/
This is just a tip on how to create dynamic if conditions. Now you know how to create dynamic if conditions.
Code accordingly to your needs !

Angular filter with minimum and maximum values

I'm having some trouble getting angular to properly filter my results. I'm attempting to use a custom filter that gets arguments from a minimum input and a maximum input.
/index.html
<input ng-model="minHorsepower">
<input ng-model="maxHorsepower">
...
tr(ng-repeat="plane in planes | filter:horsepowerFilter")
/controllers.js
//Horsepower filter
$scope.horsepowerFilter = function(plane) {
var ret = true;
if($scope.minHorsepower && $scope.minHorsepower > plane.horsepower) {
ret = false;
}
if($scope.maxHorsepower && $scope.maxHorsepower < plane.horsepower) {
ret = false;
}
return ret;
};
$scope.planes = [
{
'make' : 'Piper',
'model' : 'Arrow',
'modelNumber' : 'PA-28R-180',
'horsepower' : '180',
'gear' : 'retractable',
},
{
'make' : 'Piper',
'model' : 'Arrow',
'modelNumber' : 'PA-28R-200',
'horsepower' : '200',
'gear' : 'retractable',
}
];
It works INITIALLY when I set $scope.minHorsepower/$scope.maxHorsepower in controllers.js, but only initially, not when I put something else in the <input>s. Furthermore, it prefills the inputs AND filters the results. It just doesn't work properly when I change the value of the inputs.
I've referenced this Stack Overflow thread, but I can't find any material differences in our code... AngularJS multiple filter with custom filter function
Thanks for the help.
To ensure the model values are numbers and not strings, change the type for your inputs to be number.
<input type="number" ng-model="minHorsepower" />
<input type="number" ng-model="maxHorsepower" />
Also, make sure your model values are numbers and not strings.
Alternatively, you can run everything through parseFloat(...) in your filter.
Unfortunately, I can't pinpoint exactly the problem you're having with your code. However, I think I have created a plnkr that (I believe) works as intended.
Apart from parsing the inputs with parseFloat, the logic seems to be the same. Not parsing the inputs to a numeric form shouldn't "break" it, but will possibly make it behave strangely ("9" > "10" for example).
Anyway, hopefully you can pull out the useful pieces and get it working.
Since you only send to the filter a function, it doesn't know to watch for any value changes, and thus to trigger the filter function when it happens.
When you define a filter as {{ filter_expression | filter : filterValue}}, angular watches the filterValue and triggers the filter function when it changes.
To achieve what you need you can define your own filter:
angular.module('myApp')
.filter('range', function(){
return function(items, property, min, max) {
return items.filter(function(item){
return item[property] >= min && item[property] <= max;
});
};
});
and call it like this:
ng-repeat="plane in planes | range : 'horsepower' : minHorsepower : maxHorsepower"

Categories