ng2-search-filter
ng2-search-filter copied to clipboard
Search on particular property
Hi,
I want to search on particular property of object instead of search on whole object.
hey , Acc to the example on readme , just put the values of that particular property of all objects in the items[] array thus filtering will happen based on its contents i.e the desired property.
Thanks for quick reply. Actually I want to keep the other property e.g. place_id with search result for other operation but want to search on particular property e.g. place name.
Okay , you can always search on a particular field and you would get the whole object with it . After that use any property of that object you require.
Like like, I didn't specify requirement correctly.
How to pass single property to search? . In following example i want to search only on name property. If i search 11 as search string then it shouldn't show anything, currently It searching on all properties of object that why getting ABC into search result. e.g. let items= [{_id:'11', name: "ABC" }, {_id:'12', name: "PQA" }, { _id:'13', name: "XYZ" }];
I'd like to ask this too. I have lengthy models with lots of misc and meta fields, is it possible to filter a list by only one of those fields?
Alternatively, is it possible to display only the field that is being matched? i.e. if search "123 fake st" result would be {{id}}{{name}} (<-- shows every time) {{address}} (<-- matched field) instead of everything (about 20 more fields)
Edit: Thanks for making this by the way, great work.
I would love to accept a PR providing this functionality.
I am facing same issue ! Can anyone tell me if i want to search based on multiple fields instead of only one. can i do so ?
I want to bind multiple search term to multiple fields of dataset.
For example, my dataset is like this,
items : any = [{ id:1, first_name : "ashish", middle_name : "B", last_name : "narola", industry : "Information & technology", country : "india", state : "gujarat", investment : 50000, ROI:10 // its percentage i.e. 10% }, { id:2, first_name : "usman", middle_name : "", last_name : "shaikh", industry : "Finance", country : "india", state : "maharashtra", investment : 40000, ROI:7 // its percentage i.e. 7% }, { id:3, first_name : "indrajit", middle_name : "", last_name : "kaplatiya", industry : "Stock Market", country : "india", state : "gujarat", investment : 90000, ROI:11 // its percentage i.e. 11% } ];
I have different filters like this,
- Name - with textbox // user can enter part of full name here
- Industry - its dropdown // user can select industry from dropdown to be search for specific industry
- Country - its dropdwon // user can select country from dropdown to be search for specific country
- ROI - its textbox number input // where user can input number of percentage so search percentage of ROI greater than that and so on.
Can anyone tell me how can i achieve this ?
Thanks in advance ! Ashish B. Narola
@apa-narola I am facing a similar issue, currently ng2-search-filter
doesn't support filtering for a specific property, so I made a custom pipe like this:
transform(values: any[], filterMap: any, numberToShow: number) {
if (!values) return values;
if (!filterMap) return values;
return values.filter(value => {
return this._filter(value, filterMap, numberToShow);
});
}
_filter(item: any, filterMap: any, numberToShow: number) {
let cont = 0;
for (let property in filterMap) {
if (!item.hasOwnProperty(property)) {
continue;
}
if (!item[property]) {
continue;
}
if (filterMap[property] === '*') {
cont++;
continue;
}
if (item[property].toString().toLowerCase().includes(filterMap[property].toLowerCase())) {
cont++;
continue;
}
}
return cont === numberToShow;
}
This receive a map like this:
{
"property": "filterValue"
}
And
{{ array | filter:filterObj:3 }}
This is not the ideal case, but works for me because I need a "and" between all properties, if you need an "or", you can change the _filter
function to return true instead of add one to count.
@aVolpe Thank you very much for your reply to the comment, I shall try the way which you had suggested.
Might I suggest the following changes to add this functionality. In adding a third optional string variable that defines the object's field to use as a compare. The following change checks for a null or undefined 3rd parameter. If so, just do as normal. If not, then just return the value of
12a13
> * @param objectFieldName (optional)
14c15
< transform(items: any, term: string): any {
---
> transform(items: any, term: string, objectFieldName: string): any {
17c18
< return Ng2SearchPipe.filter(items, term);
---
> return Ng2SearchPipe.filter(items, term, objectFieldName);
24c25
< *
---
> * @param objectFieldName
26c27
< static filter(items: Array<{ [key: string]: any }>, term: string): Array<{ [key: string]: any }> {
---
> static filter(items: Array<{ [ key: string ]: any }>, term: string, objectFieldName: string): Array<{ [ key: string ]: any }> {
29a31
> if ( objectFieldName === null || objectFieldName === undefined ) { // Object Field not defined so loop over object
40c42,46
< });
---
> })
> }
> return items.filter( function(item:any) {
> return (item[objectFieldName].toString().toLowerCase().includes(toCompare)) ;
> })
42a49
>
Here is the entire typescript source. I created a filter module and used this successfully with and without the field name. Note - If you use a field name, it must be a string or a string variable.
import { Pipe, PipeTransform, Injectable } from '@angular/core';
@Pipe({
name: 'filter',
pure: false
})
@Injectable()
export class MySearchPipe implements PipeTransform {
/*
* @param items object from array
* @param term term's search
* @param objectFieldName (optional)
*/
transform(items: any, term: string, objectFieldName: string): any {
if ( !term || !items ) return items;
return MySearchPipe.filter(items, term, objectFieldName);
}
/*
* @param items List of items to filter
* @param term a string term to compare with every property of the list
* @param objectFieldName
*/
static filter(items: Array<{ [ key: string ]: any }>, term: string, objectFieldName: string): Array<{ [ key: string ]: any }> {
const toCompare = term.toLowerCase();
if ( objectFieldName === null || objectFieldName === undefined ) { // Object Field not defined so loop over object
return items.filter(function (item: any) {
for ( let property in item ) {
if ( item[ property ] === null || item[ property ] == undefined ) {
continue;
}
if ( item[ property ].toString().toLowerCase().includes(toCompare) ) {
return true;
}
}
return false;
})
}
return items.filter( function(item:any) {
return (item[objectFieldName].toString().toLowerCase().includes(toCompare)) ;
})
}
}
Example use in your template. (Note class and style information has been removed)
<table>
<thead>
<tr>
<th>
<label for="allItems">Product</label>
<input id="allItems" type="text" placeholder="Search" [(ngModel)]="searchProduct"/>
</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let productItem of productInfo |filter:searchProduct:'plName'">
<td>{{productItem.plName}}</td>
</tr>
</tbody>
</table>
Like like, I didn't specify requirement correctly.
How to pass single property to search? . In following example i want to search only on name property. If i search 11 as search string then it shouldn't show anything, currently It searching on all properties of object that why getting ABC into search result. e.g. let items= [{_id:'11', name: "ABC" }, {_id:'12', name: "PQA" }, { _id:'13', name: "XYZ" }];
Did you got a fix for this ?