angular filter in ng-repeat with <= - angularjs

I'm using angular and ng-repeat to iterate over data. I want to show only items where purchased-used <=5, but it is showing 5, 4, 55, 3, 33, 2, etc., as the result set where it should only show 5,4,3,2.
$scope.users = [{
first_name: 'Richard',
last_name: 'Grayson',
purchased: 50,
used: 10,
},
{
first_name: 'Donna',
last_name: 'Troy',
purchased: 6,
used: 3,
}]
And then on the page:
<tr ng-repeat="user in users | filter:user.purchased-user.used<=5:true">
Dick should not show in the list, but Donna should. They both show up though.
I know I could write a function for the filter, but this seems like such a simple comparison that I shouldn't have to. It seems like it should work, but there's something I'm missing.
Thanks!

You just have to make a custom filter:
$scope.customFilter = function(user){
return user.purchased-user.used <= 5;
};
And call it from your repeater:
<tr ng-repeat="user in users | filter: customFilter">

Related

How to filter values of <select> in angularjs?

I want to filter the values of a <select>.
I have a table with first column <select> .
For eg: object for the <select> is
JSON:
json1 = [{id: 1, name: 'ABC'}, {id: 2, name: 'DEF'}, {id: 3, name: 'XYZ'}, {id: 4, name: 'ASD'}, {id: 5, name: 'QWE'}]
json2 = [{id: 1, name: 'ABC'}, {id: 2, name: 'DEF'}]
My requirement is: We need to show values from json1 in ng-options but which object should not be there in json2.
For eg: First 2 rows will be filled with json2. So we need to provide options 'XYZ' 'ASD' and 'QWE' in the following rows.
Suppose if name 'XYZ' is selected in the dropdown of the third row. then 4th row <select> should show only 'ASD', and 'QWE'. Similarly what ever object selected in other rows shouldn't be shown in option of other rows dropdown.
I have tried something like this
<select ng-model="obj"
ng-options="obj.id as obj.name for obj in json1 | myFilter:json2">
</select>
myApp.filter('myFilter', function(json2) {
return function(json1) {
var filtered = [];
json1.forEach((d) => {
var exists = false;
json2.forEach((ad) => {
if(ad.id == d.id) {
exists = true;
}
});
if(!exists) filtered.push(d);
});
console.log(filetered);
return filtered.length > 0 ? filtered : json1;
};
});
In filter console.log() values are filtered correctly as expected. However in ng-options all options from json1 are still available not updated with filtered values.
What's wrong?
Is this what you are looking for?
For example:
<table>
<thead>
<tr>
<th>Unique</th>
<th>Name</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="product in products">
<td>
<select ng-model="product.unique" ng-options="obj.id as obj.name for obj in (json1 | myfilter:products:$index)">
<option value="">No select</option>
</select>
</td>
<td ng-bind="product.name"></td>
</tr>
</tbody>
</table>
vm.products = [{name: 'Product 1'}, {name: 'Product 2'}, {name: 'Product 3'}, {name: 'Product 4'}, {name: 'Product 5'}];
vm.json1 = [{id: 1, name: 'ABC'}, {id: 2, name: 'DEF'}, {id: 3, name: 'XYZ'}, {id: 4, name: 'ASD'}, {id: 5, name: 'QWE'}];
App.filter('myfilter' , [function() {
return function(json1, products, index) {
// Filter all products, except the mime
productsFilter = products.filter(function(product, i) {
return i !== index;
});
// filter those that have not yet been selected
var json1Filter = json1.filter(function(item) {
// ask if there is the id in a product
return !productsFilter.some(function(product) {
return item.id == product.unique;
});
});
return json1Filter;
};
}]);
Example Codepen: https://codepen.io/anon/pen/vMJyLz
I think you have the parameters to your filter slightly wrong. The filter function takes a first parameter as the value to be filtered and the other parameters are the ones after myFilter:.
I'm not 100% sure what you want to happen here, but your filter function is called for each value in the dropdown list and should return a replacement for the given value.
However, your code is returning an array of items. This is not how a filter works in AngularJS.
Your filter needs to be updated to check if the item being passed into the filter should be shown or not, and if not, return false.
You can look at the script example from the AngularJS docs to see how they show to do this, or this other Stack Overflow question/answer.

Using filter on angular ng-repeat

I am trying to filter to just one store, given the store Id, which is picked in a dropdown.
HTML:
<tbody data-ng-repeat="store in orderVm.Stores | filter :{store.id=orderVm.Stores.selectedStore.id}">
I don't get how to set up the filter so that it only shows the one store with the specified id.
controller:
vm.Stores = json;// from file
vm.Stores.selectedStore = {
id: vm.Stores[0].Id,
name: vm.Stores[0].MarketplaceName
};
vm.Stores:
[
{
"Id": 1,
"MarketplaceId": 1,
"MarketplaceName": "Etsy"
]
},
{
"Id": 2,
"MarketplaceId": 2,
"MarketplaceName": "Shopify"
}
]
The error I get is unexpected%2C%20expecting%20%5B%3A%5D&p2=32&p3=orderVm.Stores%20%7CNaNilter%20%3A%7Bstore.id%3DorderVm.Stores.selectedStore.id%7D&p4=.id%3DorderVm.Stores.selectedStore.id%7D
Simple to filter your data by value:
<tbody data-ng-repeat="store in orderVm.Stores | filter:Vm.Stores.selectedStore.id">
It will get objects with properties have value is Vm.Stores.selectedStore.id. Because name not is a number (id), you can use this filter for it.
To specific filter by value of id:
<tbody data-ng-repeat="store in orderVm.Stores | filter:{Id:Vm.Stores.selectedStore.id}:true">
Syntax: filter:{propertyName:value}:true
true is for exact match.

how to get formatted/require json array as per dynamic data

I'm having two dropdowns(ddls). when page loads, first ddl gets loaded with data. User can make his choice in first ddl and according to that second ddl gets filled with source(happens dynamically every time).
below these dropdowns, there is add button. if user clicks add button again in new row two dropdowns come and same scenario is then applicable. more no of rows can be added by add buttons .
beside two ddls, there is one remove buttons by pressing which particular row can be deleted.
No question is how can i get desire json array in specific format as described below.
i want json array like this....
$scope.project=[{
securityId: "first Dropdown selected value" ,
contactId:"second Dropdown selected value"
}]
(if there is only one row)
for 2 rows, I want length size 2 of $scope.project with desire and appropriate values.
for nth rows, the length of $scope.project should be n with appropriate values....
Once have a look at already made fiddle, you will come to know more. please check your browser console. I'm getting $scope.project array but not in required format.
It could be very easy for angular lovers. I don't know why i'm not getting the solution.
http://jsfiddle.net/micronyks/ZwwH7/6/
html
<html ng-app>
<div ng-controller="ctrl">
<div ng-repeat="additional in additionals">
<select ng-model="additional.securityId" ng-change="selectRoles(additional.securityId,additional)" ng-options="w.securityId as w.securityRoleName for w in SecurityRoles"></select>
<select ng-model="additional.personId" ng-change="selectperson(additional.personId,additional)" ng-options="w.personId as w.personName for w in additional.Personsddl"></select>
<button ng-click="remove($index)">remove</button>
</div>
<button ng-click="add()">add row</button>
</div>
</html>
.js file...
function ctrl($scope) {
$scope.additionals=[{}];
$scope.project=[{}];
$scope.SecurityRoles = [{
securityId: 1,
securityRoleName: "SuperAdmin"
}, {
securityId: 2,
securityRoleName: "Admin"
}
, {
securityId: 3,
securityRoleName: "Guest"
}];
$scope.Persons = [{
personId: 1,
contactId:1,
personName: "john"
}, {
personId: 2,
contactId:1,
personName: "jack"
},{ personId: 3,
contactId:2,
personName: "Johnson"
},{ personId: 4,
contactId:2,
personName: "rock"
},
{ personId: 5,
contactId:3,
personName: "bank"
}];
$scope.selectRoles=function(id,additional)
{
additional.Personsddl=[];
angular.forEach($scope.Persons,function(record){
if(record.contactId==id)
{
additional.Personsddl.push(record);
}
});
$scope.project.push({roleId:id});
}
$scope.add=function()
{
$scope.additionals.push({});
}
$scope.remove=function($index){
$scope.additionals.splice($index,1);
}
$scope.selectperson=function(id)
{
$scope.project.push({contactId:id});
console.log($scope.project);
}
}
please see here: http://jsfiddle.net/9pqjN/
HTML:
<html ng-app>
<div ng-controller="ctrl">
<p>Project :</p> <pre>{{project |json}}</pre>
<div ng-repeat="user in project">
<select ng-model="user.securityId" ng-options="w.securityId as w.securityRoleName for w in SecurityRoles"></select>
<select ng-model="user.personId" ng-options="w.personId as w.personName for w in Persons"></select>
<button ng-click="remove($index)">remove</button>
</div>
<button ng-click="add()">add row</button>
</div>
</html>
js:
function ctrl($scope) {
$scope.additionals = [];
$scope.project = [];
$scope.SecurityRoles = [{
securityId: 1,
securityRoleName: "SuperAdmin"
}, {
securityId: 2,
securityRoleName: "Admin"
}, {
securityId: 3,
securityRoleName: "Guest"
}];
$scope.Persons = [{
personId: 1,
contactId: 1,
personName: "john"
}, {
personId: 2,
contactId: 1,
personName: "jack"
}, {
personId: 3,
contactId: 2,
personName: "Johnson"
}, {
personId: 4,
contactId: 2,
personName: "rock"
}, {
personId: 5,
contactId: 3,
personName: "bank"
}];
$scope.add = function () {
$scope.project.push({});
}
$scope.remove = function ($index) {
$scope.project.splice($index, 1);
}
}
sylwester has it almost. Added a filter in my case:
<select ng-model="additional.personId"
ng-options="w.personId as w.personName for w in Persons | filter:{contactId: additional.securityId}">
</select>
Here is the complete demo http://jsfiddle.net/9DcXA/1/
Also note, there is no point in having securityId as well as contactId in output json because I see you are filtering the second drop down based on the securityId matching with contactId of Persons. I suppose you meant to show securityId and personId in result.

Angularjs OrderBy on ng-repeat doesn't work

I'm trying to use AngularJS for my first project (a tournaments manager) and the orderBy filter on ng-repeat doesn't work :( I have read all the documentation about that, but nothing to do :/
So, I have vars defined on $scope like that :
$scope.order_item = "count_win";
$scope.order_reverse = false;
$scope.teams = {
100 : {
id: 100,
name: "XXX",
count_win: 1,
count_loose: 2,
goal_average: 1,
},
200 : {
id: 200,
name: "XXX",
count_win: 1,
count_loose: 2,
goal_average: 1,
},
[...]
};
Now, on my view i'm trying to reorder (first with only one order item) but never work...
<tr ng-repeat="team in teams | orderBy:order_item:order_reverse">
<td>{{team.name}}</td>
<td>{{team.count_loose}}</td>
<td>{{team.goal_average}}</td>
</tr>
The second time, I want to reorder from 2 pieces of information: count_win and goal_average if first are equal.. I try to replace $scope.order_item like that, but if with one the code doesn't work, he'll never work with 2...
$scope.order_item = ['count_win','goal_average'];
Thank you all for reading and sorry for the post size.
$scope.teams isn't an array (it's an object of objects), and the orderBy filter only works with arrays. If you make $scope.teams an array, it will work:
$scope.teams = [
{
id: 100,
name: "team1",
count_win: 3,
count_loose: 2,
goal_average: 2,
},
{
id: 200,
name: "team2",
count_win: 3,
count_loose: 2,
goal_average: 1,
},
{
id: 300,
name: "team3",
count_win: 1,
count_loose: 2,
goal_average: 1,
}
];
Or, you can add a special filter that works on objects, like this (borrowed from here):
app.filter('orderObjectBy', function() {
return function(items, field, reverse) {
var filtered = [];
angular.forEach(items, function(item) {
filtered.push(item);
});
filtered.sort(function (a, b) {
return (a[field] > b[field] ? 1 : -1);
});
if(reverse) filtered.reverse();
return filtered;
};
});
And use it like this:
<tr ng-repeat="team in teams | orderObjectBy:order_item:order_reverse">
Note that this custom filter will not work with an array of sort orders as in the second part of your question.
You don't have to create a scope parameter for your orderBy, you can directly do this in your markup if you are dealing with arrays.
<tr ng-repeat="team in teams | orderBy:count_win:false">
With two parameters, you should just do
<tr ng-repeat="team in teams | orderBy:['count_win','goal_average']">
After for a more complex order, you could create a function in your scope like so :
$scope.customOrder = function (team) {
//custom
}
And just call it like
<tr ng-repeat="team in teams | orderBy:customOrder">
Like #Jerrad said, ng-repeat only works with arrays, so you need to convert your teams object into an array to get it work properly.
ng-repeat works only on arrays, not on JSON objects.
This was already discussed here: Angular - Can't make ng-repeat orderBy work
You either have to change the JSON object to an Array, or to convert it on the fly.
The controller could then look like this:
var app = angular.module('app', []);
app.controller('Ctrl', function ($scope) {
$scope.teams = [
{
id: 100,
name: "A Team",
count_win: 1,
count_loose: 2,
goal_average: 1
},
{
id: 200,
name: "C Team",
count_win: 2,
count_loose: 3,
goal_average: 4
},
{
id: 300,
name: "B Team",
count_win: 4,
count_loose: 1,
goal_average: 8
}
];
$scope.predicate = 'name';
});
I created a fiddle here with a demo containing your data:
http://jsfiddle.net/c3VVL/

AngularJS filter only on certain objects

I have the user object defined as below.
$scope.user = [{id: 1, friends:
[
{name: 'John', age: 21, sex: 'M'},
{name: 'Brad', age: 32, sex: 'M'}
]
}]
I have the following code:
<input type="text" ng-model="searchText">
<div ng-repeat="friend in user.friends | filter:searchText">
{{friend.name}} {{friend.age}}
</div>
Here whenever I search, I get results for name, age as well as sex. But I want to search only for name and age and I don't want sex to be searchable. Can anyone help me with how I can achieve this?
You can pass an object as the second parameter to achieve this if you can have two search fields
<div ng-repeat="friend in user.friends | filter:{name:searchNameText, age:searchAgeText}">
Otherwise you'll need to write a custom filter to use the same field for both, or pass a custom filter function as the third parameter which is described in the docs.
http://docs.angularjs.org/api/ng.filter:filter
I'm not sure if this is what you are after. If you want to have one input field to matched multiple properties you need a filter function to be passed to filter.
$scope.user = {id: 1, friends: [{name: 'John', age: 21, sex: 'M'}, {name: 'Brad', age: 32, sex: 'M'}, {name: 'May', age: 64, sex: 'F'}]};
$scope.searchFilter = function (obj) {
var re = new RegExp($scope.searchText, 'i');
return !$scope.searchText || re.test(obj.name) || re.test(obj.age.toString());
};
Here's a fiddle example
http://jsfiddle.net/fredrik/26fZb/1/
This is not the cleanest way to accomplish what you want, but it is the simplest way to accomplish an OR filter using the standard ng-repeat filter.
Controller:
$scope.user = [{id: 1, friends:
[
{name: 'John', age: 21, sex: 'M'},
{name: 'Brad', age: 32, sex: 'M'}
]
}]
$scope.buildSearchData = buildSearchData;
function buildSearchData(friend){
return friend.name + ' ' + friend.age;
}
HTML
<input type="text" ng-model="searchText">
<div ng-repeat="friend in user.friends | filter:{searchData:searchText}"
ng-init="friend.searchData = buildSearchData(friend)">
{{friend.name}} {{friend.age}}
</div>
"friend in user.friends | json | filter:{something:somethingtext}"
http://docs-angularjs-org-dev.appspot.com/api/ng.filter:json
Another possible approach is to create an aggregate field that contains the values of all of the fields you want to filter on concatenated and only filter on that.

Resources