Angularjs: Search filter not working when search starting with ! (exclamation mark)
If my data is like name='Anand!'
client side filter should work with searchWord='!'
Please if anyone has solution for the same then provide me the same.
Thanks in advance !!
My Code:
<input type="search" class="form-control" ng-model="searchtext"
placeholder="search here..." />
<div ng-repeat="cust in customers |orderBy:'id' | filter:searchtext">
</div>
$scope.customers = [{
"id": 1,
"first_name": "Anand!",
"last_name": "GK",
"gender": "Male"
}, {
"id": 2,
"first_name": "ABC !",
"last_name": "XYZ",
"gender": "Female"
}];
In above example you provide the filter on first_name only and also the function will be common for all so we can use it any where
this can be achieved too, all you have to do is get values of all fields in your object and then match the searchText like following:-
All you need to do, is write a custom filter of your own
angular.module('app', []).controller('ctrl', function($scope) {
$scope.customers = [{
"id": 1,
"first_name": "Anand!",
"last_name": "GK",
"gender": "Male"
}, {
"id": 2,
"first_name": "ABC !",
"last_name": "XYZ",
"gender": "Female"
}];
}).filter('searchFilter', function() { /* this the Custom Filter, you can code it to include other fields in search too */
return function(input, searchText) {
if (!searchText)
return input;
var matchedRecord = [];
var matchFound = false;
for (var i = 0; i < input.length; i++){
for (var key in input[i]) {
if(input[i][key] != undefined && input[i][key].toString().toLowerCase().indexOf(searchText.toLowerCase()) != -1) {
matchFound = true;
}
}
if(matchFound)
matchedRecord.push(input[i]);
matchFound = false;
}
return matchedRecord;
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app='app' ng-controller='ctrl'>
<input type='text' ng-model='searchText' />
<ul>
<li ng-repeat='customer in customers | searchFilter: searchText'>{{customer | json}}</li>
</ul>
</div>
Related
I'm developing an app using Angular 1.5.5. I'm trying to filter an array of Location objects by ID. The Locations array has 10 objects in it. The filter is returning 2 objects instead of the of the one:
Locations Array:
My html template looks like:
<div class="col-md-3" ng-repeat="location in offerings.Locations | filter : {'ID':event.LocationID}">
{{location.Name}}<br />
{{location.Address}}, {{location.City}}, {{location.State}} {{location.Zip}}<br />
Loc ID = {{location.ID}} eventLocID = {{event.LocationID}}
</div>
It's returning 2 results instead of the filter where 2 = 2:
You could try write own filter function or use that construction:
ng-repeat="location in offerings.Locations | filter : {'ID':event.LocationID} : true"
Also check this topic Filter array of objects by attribute with integer value in ng-repeat
DEMO
var myApp = angular.module('myApp',[]);
myApp.controller('MyCtrl', function($scope) {
$scope.event = {"LocationID" : 2}
$scope.locations = [
{
"Address": "address1",
"city": "city1",
"ID": 2,
"Name": "name1",
"State": "state1",
"Zip": 243435
},
{
"Address": "address2",
"city": "city2",
"ID": 3,
"Name": "name2",
"State": "state2",
"Zip": 243435
},
{
"Address": "address3",
"city": "city3",
"ID": 12,
"Name": "name3",
"State": "state3",
"Zip": 243435
}
];
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp" ng-controller="MyCtrl">
<div class="col-md-3" ng-repeat="location in locations | filter:{'ID' : event.LocationID}:true">
{{location.Name}}<br />
{{location.Address}}, {{location.City}}, {{location.State}} {{location.Zip}}<br />
Loc ID = {{location.ID}} eventLocID = {{event.LocationID}}
</div>
</div>
I'm trying to filter a nested array of objects with my own objects, by idSubject. But I'm not getting the right result.
I have articles (which have subjects)
And a array of objects (which are the subjects I want to filter the articles with)
Data looks like this:
So I'm trying to filter the array of articles by its subjects.
I tried the following:
<div class="panel panel-default"
ng-repeat="searchArticle in searchArticles | filter: {subjects: filterSubjects} as articleSearchResult">
So filterSubjects is the second screenshot and SearchArticles is the first screenshot.
Without much luck.
Hope you can help, please tell me if things are still unclear.
This custom filter will help you.
Example : http://plnkr.co/edit/jMizCLxPH6DtDA5wL15Q?p=preview
HTML:
<body ng-app="myApp">
<div ng-controller="MainCtrl">
<h2>Select Subjects</h2>
<div ng-repeat="subject in subjects">
<label>
<input type="checkbox" ng-model="filterSubjects[subject.id]" ng-true-value="'{{subject.id}}'" ng-false-value="''">{{subject.name}}</label>
</div>
<h2>Filtered Articles</h2>
<div ng-repeat="searchArticle in searchArticles | subjectFilter:filterSubjects">{{searchArticle.name}}</div>
</div>
</body>
JS:
var app = angular.module('myApp', []);
app.controller('MainCtrl', function($scope) {
$scope.searchArticles = [{
"name": "Article1",
"sid": "1"
}, {
"name": "Article2",
"sid": "1"
}, {
"name": "Article3",
"sid": "2"
}];
$scope.subjects = [{
"name": "Subject1",
"id": "1"
}, {
"name": "Subject2",
"id": "2"
}];
$scope.filterSubjects = [];
});
app.filter('subjectFilter', function() {
return function(articles, filterSubjects) {
filtered = articles.filter(function(e){return filterSubjects.indexOf(e.sid) >= 0},filterSubjects);
return filtered;
}
});
if you want to filter based on object :
var app = angular.module('myApp', []);
app.controller('MainCtrl', function($scope) {
$scope.searchArticles = [{
"name": "Article1",
"sid": "1"
}, {
"name": "Article2",
"sid": "1"
}, {
"name": "Article3",
"sid": "2"
}];
$scope.subjects = [{
"name": "Subject1",
"id": "1"
}, {
"name": "Subject2",
"id": "2"
}];
$scope.filterSubjects = [{
"name": "Subject1",
"id": "1"
}, {
"name": "Subject1",
"id": "2"
}];
});
app.filter('subjectFilter', function() {
return function(articles, filterSubjects) {
var sFiltered = [];
for (var i = 0; i < filterSubjects.length; i++) {
sFiltered.push(filterSubjects[i].id);
}
var filtered = articles.filter(function(e) {
return sFiltered.indexOf(e.sid) >= 0;
}, sFiltered);
return filtered;
}
});
Hi I have a Json Like this
[
{
"id": 1,
"name": "Furniture & Fixture",
"choices": [
{
"req_goods": "",
"qty": "10",
"rate": "",
"total": ""
}
]
},
{
"id": 2,
"name": "Miscellaneous Property",
"choices": [
{
"req_goods": "",
"qty": "",
"rate": "",
"total": ""
}
]
},
{
"id": 3,
"name": "Office Equipment",
"choices": [
{
"req_goods": "",
"qty": "",
"rate": "",
"total": ""
}
]
}
]
here choices are my dynamic fields user can add as much choices as they want, my add/remove js is like this
$scope.addNewChoice = function(id){
$scope.capital_budgets[id].choices.push({});
};
$scope.removeChoice = function(parent_id,id) {
$scope.capital_budgets[parent_id].choices.splice(id,1);
};
my html
<div ng-repeat="cb in capital_budgets">
<div><b><% $index+1 %> <% cb.name %></b></div>
<div ng-repeat="choice in cb.choices">
<input type="text" ng-model="choice.req_goods">
<input type="text" ng-model="choice.qty">
<input type="text" ng-model="choice.rate">
<input type="text" ng-model="choice.total">
<button type="button" ng-hide="$first" ng-click="removeChoice($parent.$index,$index)">-</button>
</div>
<button type="button" ng-click="addNewChoice($index)">+</button>
</div>
Now I want to calculate the total(qty*rate) of each added choices whenever they put qty and rate and put it in total field please help
One way to accomplish this would be to create a method in your controller to do the calculation and then just call it on a change of qty or rate.
controller:
$scope.updateTotal = function(choice) {
if(!choice.qty || !choice.rate) {
choice.total = 0;
} else {
choice.total = choice.qty * choice.rate;
}
};
html:
<input type="text" ng-model="choice.qty" ng-change="updateTotal(choice)">
<input type="text" ng-model="choice.rate" ng-change="updateTotal(choice)">
I have a simple set of ng-options. Each child ng-options is supposed to narrow down its data based on the parent being populated.
However, for repeating the main parent - 'Country' i introduced the unique filter as it was repeating items, for example without the filter UK was present twice in the drop down.
However, after selecting UK, i would expect to see London and Leeds in the Cities dropdown, however only London is present.
HTML:
<label>Country</label>
<select ng-model="country" ng-options="country as country.Country for country in Data | unique:'Country'">
<option value="">--Countries--</option>
</select>
<br>
<label>City</label>
<select ng-model="city" ng-options="city as city.City for city in Data | filter:country">
<option value="">--Cities--</option>
</select>
<br>
<label>Job Category</label>
<select ng-model="category" ng-options="category as category.Category for category in Data | filter:city">
<option value="">--Job Category--</option>
</select>
JS:
app.controller('MainCtrl', function($scope) {
$scope.name = 'World';
$scope.Data = [{
"Country": "UK",
"City": "London",
"Department": "Finance",
"rank": "2"
}, {
"Country": "UK",
"City": "Leeds",
"Department": "IT",
"rank": "3"
}, {
"Country": "USA",
"City": "Texas",
"Department": "Risk",
"rank": "5"
}];
});
app.filter('unique', function() {
return function(items, filterOn) {
if (filterOn === false) {
return items;
}
if ((filterOn || angular.isUndefined(filterOn)) && angular.isArray(items)) {
var hashCheck = {}, newItems = [];
var extractValueToCompare = function(item) {
if (angular.isObject(item) && angular.isString(filterOn)) {
return item[filterOn];
} else {
return item;
}
};
angular.forEach(items, function(item) {
var valueToCheck, isDuplicate = false;
for (var i = 0; i < newItems.length; i++) {
if (angular.equals(extractValueToCompare(newItems[i]), extractValueToCompare(item))) {
isDuplicate = true;
break;
}
}
if (!isDuplicate) {
newItems.push(item);
}
});
items = newItems;
}
return items;
};
});
Here's my plunkr: http://plnkr.co/edit/wPCex3lJc5E0I4fSeXI1?p=preview
The problem is not with the unique filter but with the value in $scope.country. It's not a string containing the country but the object that contains the country e.g.
{
"Country": "UK",
"City": "London",
"Department": "Finance",
"rank": "2"
}
If you change the filter on the city to 'country.Country' then it will work.
Even better would be to rename country in the expression "country as country.Country for country in Data | unique:'Country'" to something like "item as country.Country for country in Data | unique:'Country'" and use item.Country in the city filter.
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?
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"
}]
}
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.
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>
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.
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.