Reputation: 621
I have a JSON object which is as follows
[{
"id": 1,
"firstName": "Jennifer",
"middleName": null,
"lastName": "Aniston",
"address": "New York City",
}, {
"id": 2,
"firstName": "Angelina",
"middleName": null,
"lastName": "Jolie",
"address": "Beverley Hills",
}, {
"id": 3,
"firstName": "Emma",
"middleName": null,
"lastName": "Watson",
"address": "London",
}]
I'm populating this data in view using ng-repeat.
<td ng-repeat="row in list | filter:filterBeauties">
{{row.firstName}} {{row.lastName}}
</td>
Now I have an input box which I'd like to use to filter these names. I would like to use same input box to filter firstName and then filter lastName and don't filter anything else (eg. address).
<input type="text" placeholder="Filter" ng-model="filterBeauties.firstName">
Any idea how can I achieve it?
Upvotes: 7
Views: 35990
Reputation: 23737
Try the angular-filter
library instead of writing complex filters. The searchField
filter can be helpful here.
https://github.com/a8m/angular-filter
CONTROLLER
$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 -->
Good Luck.
Upvotes: 3
Reputation: 525
Considering that your user have this form:
{
"id": 2,
"firstName": "Angelina",
"middleName": null,
"lastName": "Jolie",
"address": "Beverley Hills"
}
If you want to search one of your user by his firstname, his lastname or both at the same time, you need to concat them together.
$scope.query = '';
$scope.search = function (user) {
var query = $scope.query.toLowerCase(),
fullname = user.firstName.toLowerCase() + ' ' + user.lastName.toLowerCase();
if (fullname.indexOf(query) != -1) {
return true;
}
return false;
};
This function will return true
if the current user satisfies your query and false
if not. Inside of the function, I recommend to put your query in lowercases so you won't have to deal with the uppercases your user will enter in the search input.
Here is the HTML:
<input type="text" placeholder="Search" ng-model="query">
<table>
<tr ng-repeat="user in users | filter:search">
<td>{{user.firstName}} {{user.lastName}}</td>
</tr>
</table>
This technic will only work if you try to search Angelina Jolie
, Angelina
, Jolie
or even InA JOLIe
(why not after all). If you try to search first the lastname like Jolie Angelina
, it won't work. You can easily fix it by creating a second fullname in your function (e.g. a reverseFullname
), concat in first the lastName and then the firstName and test it just like the first fullname string.
Upvotes: 6
Reputation: 13457
Try this fiddle.
Essentially, I created a sub-structure for filtering within the data structure being displayed and filter only on that property (e.g. 'filterTerms'):
HTML:
<div ng-controller="MyCtrl">
<input type="text" ng-model="search.filterTerms">
<table border="1">
<tr ng-repeat="row in list | filter:search">
<td>{{row.firstName}} {{row.lastName}}</td>
</tr>
</table>
</div>
JavaScript:
var myApp = angular.module('myApp',[]);
function MyCtrl($scope) {
$scope.list = [{
"id": 1,
"address": "New York City",
"firstName": "Jennifer",
"middleName": null,
"lastName": "Aniston",
"filterTerms": {
"firstName": "Jennifer",
"middleName": null,
"lastName": "Aniston",
}
}, {
"id": 1,
"address": "New York City",
"firstName": "Jennifer",
"middleName": null,
"lastName": "Leela",
"filterTerms": {
"firstName": "Jennifer",
"middleName": null,
"lastName": "Leela",
}
}, {
"id": 2,
"address": "Beverley Hills",
"firstName": "Angelina",
"middleName": null,
"lastName": "Jolie",
"filterTerms": {
"firstName": "Angelina",
"middleName": null,
"lastName": "Jolie",
}
}, {
"id": 3,
"address": "London",
"firstName": "Emma",
"middleName": null,
"lastName": "Watson",
"filterTerms": {
"firstName": "Emma",
"middleName": null,
"lastName": "Watson",
}
}];
}
You could simplify this even further for this case by putting all the names into one field (see fiddle here:
HTML:
<div ng-controller="MyCtrl">
<input type="text" ng-model="search.filterTerm" />
<table border="1">
<tr ng-repeat="row in list | filter:search">
<td>{{row.first}} {{row.last}} {{row.address}}</td>
</tr>
</table>
</div>
JavaScript:
var myApp = angular.module('myApp', []);
function MyCtrl($scope) {
$scope.list = [{
"id": 0, "first": "Jenny", "last": "Sorenson", "address": "123 W. Wallnut St.",
"filterTerm": "Jenny Sorenson"
},{
"id": 0, "first": "Susan", "last": "Hinkle", "address": "456 W. Doorbell Dr.",
"filterTerm": "Susan Hinkle"
},{
"id": 0, "first": "Rachel", "last": "Karlyle", "address": "789 W. Sunset Blvd.",
"filterTerm": "Rachel Karlyle"
},{
"id": 0, "first": "Gwen", "last": "Lippi", "address": "0 W. Silly Cir.",
"filterTerm": "Gwen Lippi"
}]
}
Upvotes: 6
Reputation: 621
Okay So this is what I did to solve it.
I added a new item in json object (using angular.forEach function) and filtered by it.
$scope.list = beauties.query(function(response) {
angular.forEach(response, function(value, key) {
var fullName = value.firstName + ' ' + value.lastName;
$scope.list[key].fullName = fullName;
});
});
input box code:
<input type="text" placeholder="Filter" ng-model="filterBeauties.fullName">
ng-repeat
<td ng-repeat="row in list | filter:filterBeauties">
{{row.firstName}} {{row.lastName}}
</td>
Upvotes: 4
Reputation: 10530
You can pass the third argument to the filter function:
$filter('filter')(list, {'firstName':search});
I would have done something like below:
<input type="text" ng-model="search">
<table border="1">
<tr ng-repeat="row in list | filterBoth:search">
<td>{{row.firstName}} {{row.lastName}}</td>
</tr>
</table>
And then write the custom filter as:
myApp.filter('filterBoth', function($filter) {
return function(list, search) {
if (!search) return list;
var arrSearch = search.split(' '),
lookup = '',
result = [];
arrSearch.forEach(function(item) {
lookup = $filter('filter')(list, {'firstName': item});console.log(lookup);
if (lookup.length > 0) result = result.concat(lookup);
});
return result;
};
});
Demo: http://jsfiddle.net/wAp4S/1/
The only issue is you will get duplicate rows as you are concatenating two similar arrays which can easily be fixed using _.uniq
underscore.js method.
Upvotes: 3