angular ng-repeat filter by number - angularjs

I'm having some trouble filtering an list by type (number) in angular (1.5.8)
my ng repeat with filter is as following:
ng-repeat="activity in guild.history_updates | filter : {
action_type: filters.action_type,
user_id: filters.user,
}"
and my filter
<md-input-container class="md-block">
<label>Type</label>
<md-select ng-model="filters.action_type">
<md-option>
All
</md-option>
<md-option ng-repeat="action_type in guildActivityCtrl.action_types"
ng-value="action_type.type">
{{action_type.name}} ({{ action_type.type }})
</md-option>
</md-select>
</md-input-container>
When I'm filtering on action_type 1 I'm also getting action types 10
But when I chage the filter to 10, I'm getting the right results
Every other action type is filtered good as well (e.g. action_type 3)

ng-repeat="activity in guild.history_updates | filter:{action_type:filters.action_type,user_id: filters.user}:true"
Adding ":true" after your filter should change this to a strict equality check, now comparing the numeric values.
Hope this helps.
https://docs.angularjs.org/api/ng/filter/filter
The Arguments section defines the comparator.

Like Neal Hamilton said, we need to add :true to add a strict equality check.
Adding :true won't work when the output of the md-select isn't a number so we can add a filter to parse the output to a number like:
.filter('parseInt', function() {
return function(number) {
if(!number) {
return false;
}
return parseInt(number , 10);
};
})
We can add this filter to the ng-repeats' filter like:
ng-repeat="activity in guild.history_updates | filter : {
action_type: (filters.action_type | parseInt ),
user_id: filters.user,
} : true"
Edit: When you don't want to strict check every value in the filters you can use multiple filters like:
ng-repeat="activity in guild.history_updates
| filter : {
action_type: (filters.action_type | parseInt ),
} : true
| filter: {
user_id: filters.user
}"

Related

ui-select multiple: ng-model how will it be saved as string and not as array

I have this ui select:
<ui-select multiple
ng-model="meas.daysSelected"
theme="bootstrap"
close-on-select="false">
<ui-select-match placeholder="days">{{$item}}</ui-select-match>
<ui-select-choices repeat="day in days | filter:$select.search">
<div ng-bind-html="day | highlight: $select.search"></div>
</ui-select-choices>
</ui-select>
$scop.days = ['Sun', 'Mon', 'Tue' ... ]
it is in a simple table with angular ng-repeat
<tr ng-repeat="meas in foo= (res.foos | filter: subSearch : strict)">
and I filter it with:
<input type="text" class="form-control" ng-model="subSearch.daysSelected">
The problem is like this: the "daySelected" model is becoming an array when I select an object and then de-select it. the filter of angular just dismisses it and filters it.
So I need help in one of the 2:
make daySelected as a string (when selected it will be: "sun, mon"
or
adjust the filter to work in array
Assuming the search text is going to be like "Mon,Tue" which will filter all the ui-selects which have ["Mon","Tue"] you can write your own filter function and pass that. For example:
<tr ng-repeat="meas in foo= (res.foos | filter: $ctrl.filterDaysSelected">
And in your controller you'd need to create that function:
$ctrl.filterDaysSelected = function(value, index, array) {}
Where you would need to:
Split the value of your search criteria by ","
Validate that each item in your split array exists in the function value parameter

How to pass value (true or false) for sorting tabular data in Angular JS ng-repeat

I want to determine the ascending/descending property of the ng-repeat by passing a value coming from a dropdown box.
I defined a variable called "asdc" whose value is determined by a dropdown box. This variable should determine if the table will be sorted ascending or descending. The variable already created in the AngularJS controller so I don`t post it here. I am pasting the codes below. It does not work this way. I am wondering what I am missing.
This is the table that I want to sort.
<tr ng-repeat="technology in technologies | limitTo: rowlimit | orderBy: sortby : adsc" >
<td>{{technology.name | uppercase}}</td>
</tr>
This is the drowdown box. It defines the value of adsc as true or false and passes the value to "adsc".
<select ng-model="adsc">
<option value="true">Asc</option>
<option value="false">Dsc</option>
</select>
Use ng-options to bind to something other than a string:
In controller:
$scope.directions = [
{
value: false,
label: 'Asc'
},
{
value: true,
label: 'Desc'
}
];
In view:
<select name="direction" ng-model="adsc"
ng-options="direction.value as direction.label for direction in directions">
</select>
Here's a plunkr demonstrating its use.
Also, note that passing true will sort in descending order, not ascending.

How can i Apply filter by taking the arrays First value as Input On check?

Iam Learning AngularJs ...
Example : -
My Json Having an array with some values as types :-
Lets Say A Restaurant would be Mexican or Italian Etc
My example
{
name:'res 123',
description:'Italian Rest'
types:['Mexican','Indian']
}
<input type="checkbox" data-ng-model="Mexican"/> // Iam Using Textbox Oncheck Filter Need to Filter all the Objects with types:['Mexican']
Filter Code :-
<div class="col-xs-12" data-ng-repeat="obj in objs| filter : objs.types[1]: Mexican" > <!-- Filter applied Like this -->
Realted looping
</div>
How can i Apply filter by taking the types:['Mexican'] value as Input for Filter On check ?
A built-in filter in Angular accepts a hash that specifies by what properties to match against each element in an array.
So, if you have an array of restaurants:
var restaurants = [
{ name: "foo", types: ["Mexican", "Indian"] },
{ name: "bar", types: ["Mexican"] },
{ name: "baz", types: ["Italian"] }
];
then if you need to filter by name, the input to filter would be {name: 'b'} - which would give you "bar" and "baz".
Likewise, if you need to filter by types - even though it is an array - a similar approach would work: {types: "Mexican"}.
And so, you just need to construct that object - let's call it filterBy.
<input type="checkbox" ng-model="filterBy.types"
ng-true-value="'Mexican'"
ng-false-value="undefined"> Mexican
<div ng-repeat="r in restaurants | filter: filterBy>
{{r.name}}
</div>
Demo

Making an angular filter conditional

I'm currently using a text input to filter a list of items. I'd like to make it so when a particular variable is set, the list doesn't filter, regardless of what the text input is. Any advice on how I can accomplish this?
<a ng-repeat="set in data | filter: { value: search }" data-id="{{set.id}}" ng-mousedown="setBox(set)" ng-mouseover="setSelected(set, $event)" ng-bind-html="set.value | trustHTML"></a>
You can achieve this if you set the filter expression to '' (or undefined) - this causes the filter not to be applied - for when your disableFilter is set, or to the actual filter expression otherwise.
EDIT 2:
The other answer (below by #Ryan) is simpler and easier to understand. Can't remember now whether it didn't work for me initially or I simply didn't think of this simpler way.
So, assuming, this toggling variable - disableFilter - is a boolean :
<a ng-repeat="set in data | filter: (!disableFilter || '') && filterExpression">
(with filterExpression being whatever the expression you want to filter by). Your specific case would be:
<a ng-repeat="set in data | filter: (!disableFilter || '') && {value: search}">
EDIT:
To explain how the above works.
Remember that || and && return the value of one of its operands.
|| and && use short-circuit evaluation - true || (anything) returns true; false && (anything) returns false - without evaluating the (anything) expression.
'' is falsy (or use undefined instead, if it's clearer)
And so,
when disableFilter === true, !disableFilter === false, thus the second operand of || - the empty string '' - is evaluated (it's falsy), and (!disableFilter || '') returns '' - a falsy value, which short-circuits the && operation and does not evaluate the second operand of &&. The return value of the expression is thus ''.
when disableFilter === false, !disableFilter === true, which short-circuits the || operation, then the second operand of && is evaluated and returned. The return value of the expression is thus {value: search}.
Read more about logical operators here
I think the following is a slightly less tricky solution. Tricky solutions cause bugs for future developers.
Here's my suggestion:
<a ng-repeat="set in data | filter: (shouldFilter ? filterExpression : '')">
or
<a ng-repeat="set in data | filter: (shouldFilter ? {value: search} : '')">
Simply, if shouldFilter, then give it your filter expression, otherwise give it nothing.
Using a simple ternary expression will be easier for readability.
Maybe use an ng-if?
<a ng-if="!myConditional" ng-repeat="set in data" data-id="{{set.id}}" ng-mousedown="setBox(set)" ng-mouseover="setSelected(set, $event)" ng-bind-html="set.value | trustHTML"></a>
<a ng-if="myConditional" ng-repeat="set in data | filter: { value: search }" data-id="{{set.id}}" ng-mousedown="setBox(set)" ng-mouseover="setSelected(set, $event)" ng-bind-html="set.value | trustHTML"></a>
That seems to be the solution.
Here is what I did. First, I had a select control, populated from my controller, with one static item (Select...) with a zero length string value:
<select data-ng-model="districtFilter" class="form-control" data-ng-options="d.DistrictId as d.DistrictName for d in districts | orderBy: 'DistrictName'"><option value="">Select...</option></select>
Then I applied the filter conditionally on the table. It appears when the filter is null, setting it to undefined clears it:
<tr data-ng-repeat="courtEntity in courts | filter:{ 'DistrictId' : districtFilter === null ? undefined : districtFilter}">
I had a complicated case
Have a list of records say it products
Filter by two other property prop1, prop2 selected by user from drop down
Another dropdown (prop3) have two value 1 and 2, if user select 2 filter should not be applied
Hers is my outcome:
ng-repeat="prod in filterdProd =
(products | filter : model.prop3 == 2 ? '' :
{ 'prop1': model.prop1 || 'none',
'prop2': model.prop2 }) |
orderBy: 'productrName'"
if model.prop3 == 2 ? '' filter will not apply otherwise ...
We can also use the count of records by using filterdProd
I found the following solution more easy and effective
angular.module('myApp', []).controller('namesCtrl', function($scope) {
$scope.package=[{"PkgServiceId":null,"PkgServicesName":" HB, TLC, DLC & ESR, EDTA WHOLE BLOOD, HBSAG CONFIRMATION,SERUM, Blood Cholesterol","PromoDiscount":null,"PromoID":null,"ReportPeriod":5,"ServiceDesc":null,"ServiceId":108,"ServiceName":"Family Health Package"},{"PkgServiceId":108,"PkgServicesName":null,"PromoDiscount":null,"PromoID":null,"ReportPeriod":5,"ServiceDesc":null,"ServiceId":70,"ServiceName":"HB, TLC, DLC & ESR, EDTA WHOLE BLOOD"},{"PkgServiceId":108,"PkgServicesName":null,"PromoDiscount":null,"PromoID":null,"ReportPeriod":5,"ServiceDesc":null,"ServiceId":71,"ServiceName":"HBSAG CONFIRMATION,SERUM"},{"PkgServiceId":108,"PkgServicesName":null,"PromoDiscount":null,"PromoID":null,"ReportPeriod":3,"ServiceDesc":"Its used to evaluate your overall health and detect a wide range of disorders","ServiceId":2,"ServiceName":"Blood Cholesterol"},{"PkgServiceId":null,"PkgServicesName":" MRI Test, HB, TLC & DLC, EDTA WHOLE BLOOD","PromoDiscount":null,"PromoID":null,"ReportPeriod":5,"ServiceDesc":null,"ServiceId":107,"ServiceName":"Child Health Package"},{"PkgServiceId":107,"PkgServicesName":null,"PromoDiscount":null,"PromoID":null,"ReportPeriod":5,"ServiceDesc":"Its used to evaluate your overall health and detect a wide range of disorders","ServiceId":5,"ServiceName":"MRI Test"},{"PkgServiceId":107,"PkgServicesName":null,"PromoDiscount":null,"PromoID":null,"ReportPeriod":5,"ServiceDesc":null,"ServiceId":69,"ServiceName":"HB, TLC & DLC, EDTA WHOLE BLOOD"}] ;
});
<!DOCTYPE html>
<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
<body>
<div ng-app="myApp" ng-controller="namesCtrl">
<ul>
<li ng-repeat="x in package">
{{ x.ServiceName }}
</li>
</ul>
<p>Above is the total data set without filtering.</p>
<ul>
<li ng-repeat="x in package| filter :{PkgServiceId: null}">
{{ x.ServiceName }}
{{ x.PkgServiceId }}
</li>
</ul>
</div>
<p>This example displays only the packages containing the packageId "null".</p>
</body>
</html>
In HTML Template Binding
{{ dataX | date: expression ? 'dd/MM' : 'dd/MM/yyyy' }}
Make functions and combine with filterExpression.
Example I have a students list as below:
$scope.students = [
{ name: 'Hai', age: 25, gender: 'boy' },
{ name: 'Hai', age: 30, gender: 'girl' },
{ name: 'Ho', age: 25, gender: 'boy' },
{ name: 'Hoan', age: 40, gender: 'girl' },
{ name: 'Hieu', age: 25, gender: 'boy' }
];
I want to filter students via gender to be boy and filter by name of them.
The first I create a function named "filterbyboy" as following:
$scope.filterbyboy = function (genderstr) {
if ((typeof $scope.search === 'undefined')||($scope.search === ''))
return (genderstr = "")
else
return (genderstr = "boy");
};
Explaination: if not filter name then display all students else filter by input name and gender as 'boy'
Here is a demo How to use and operator in AngularJs example

angularjs ngRepeat orderBy when property key has spaces

I'm getting some data in JSON format which has spaces in the some of the keys:
[
{
"PlainKey": "SomeValue",
"Spaced Key": "SomeValue"
},
{
"PlainKey": "SomeValue2",
"Spaced Key": "SomeValue2"
}
]
This happens at some point:
$http.get('https://dl.dropboxusercontent.com/u/80497/htmlTesting/properties/credits.properties' + '?callback=JSON_CALLBACK').then(function (data) {
$scope.credits = data.data;
}, function (error) {
$scope.errorOccured = true;
console.log("Error:");
console.log(error);
});
and then ng-repeat is used to display it, with ordering:
<select ng-model="corder">
<option value="PlainKey">Plain Key</option>
<option value="Spaced Key">Spaced Key</option>
</select>
<li ng-repeat="credit in credits | orderBy:corder" >
.....
</li>
This doesn't work ( I get an exception )
(The PlainKey works because there are no spaces).
I also tried putting the values in ':
<select ng-model="corder">
<option value="'PlainKey'">Plain Key</option>
<option value="'Spaced Key'">Spaced Key</option>
</select>
This seems to change the order, but not correctly.
What Am I missing?
Thanks!
Simplest way, just surround a field name with UTF8 code for quotation mark:
HTML
<li ng-repeat="item in items | orderBy:'\u0022Spaced Key\u0022'">
JS
$scope.orderKey = '\u0022Spaced Key\u0022';
Comments appeared to help so I'm including it as an answer:
One way to sort items with spaces in their object property names is to pass a predicate sort function into orderBy instead of specifying the object property name. The relevant modifications in particular:
HTML:
<li ng-repeat="credit in credits | orderBy:predicate">
JS:
$scope.predicate = function(val) {
// $scope.corder corresponds to the object property name to sort by
return val[$scope.corder];
}
Demonstration Plunker.

Resources