In this article I will be explaining about how to implement a simple and advanced search using pipe concept. I have explained in my previous article about how to do a simple search or filtering using angular js 1 as well. If you want to compare both implementation you can refer this link.
1. Simple search using pipe in Angular
2. Example of search using different array structure
3. Advanced search using pipe in Angular
4. Search entire Array
1. Simple search using pipe in Angular
OK, let’s start with our Angular 2 simple search implementation using pipe.
I will share the app module code as well to avoid any confusion
App module code
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { HttpModule } from '@angular/http';
import {FilterPipe} from './pipes'
import { AppComponent } from './app.component';
@NgModule({
declarations: [
AppComponent,FilterPipe
],
imports: [
BrowserModule,
FormsModule,
HttpModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
FilterPipe is nothing but our pipe name and './pipe' is the typscript file path which has pipe code.
Let us check our component code
App component
import { Component } from '@angular/core';
import {FilterPipe} from './pipes'
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
title:String;
names:any;
constructor(){
this.title = "Angular 2 simple search";
this.names = ['Prashobh','Abraham','Anil','Sam','Natasha','Marry','Zian','karan']
}
}
Here you can see a simple array which contains some names. The template url is nothing but our html.
Template [ templateUrl: './app.component.html']
<div>
<h3> {{title}}</h3>
<input type="text" [(ngModel)]="queryString" id="search" placeholder="Search to type">
<ul>
<li *ngFor="let n of names | FilterPipe: queryString">
{{n}}
</li>
</ul>
</div>
Now create a pipe and name as FilterPipe. Check below code for pipe.
Pipe
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
name: 'FilterPipe',
})
export class FilterPipe implements PipeTransform {
transform(value: any, input: string) {
if (input) {
input = input.toLowerCase();
return value.filter(function (el: any) {
return el.toLowerCase().indexOf(input) > -1;
})
}
return value;
}
}
We are done. Run the application and start typing on text box you can see filtered result.
You can go to our GitHub page and download all the code as well. Download code from GitHub page.
2. Example of search using different array structure
Now let us check with another example, above example is searching through a simple list. We will modify our array and see how it will work.
Modified Array
this.list = [
{name:'prashobh',age:'25'},
{name:'Abraham',age:'35'},
{name:'Sam',age:'45'},
{name:'Anil',age:'15'},
{name:'Mariya',age:'24'},
{name:'Crock',age:'28'},
{name:'Ram',age:'21'},
]
Modified pipe
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
name: 'FilterPipe',
})
export class FilterPipe implements PipeTransform {
transform(value: any, input: string) {
if (input) {
input = input.toLowerCase();
return value.filter(function (el: any) {
return el.name.toLowerCase().indexOf(input) > -1;
})
}
return value;
}
}
I just updated to "el.name", it will search through the array and find the respective names. Ok now let us check with another example which can search through both age and name.
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
name: 'FilterPipe',
})
export class FilterPipe implements PipeTransform {
transform(value: any, input: string) {
if (input) {
input = input.toLowerCase();
return value.filter(function (el: any) {
return el.name.toLowerCase().indexOf(input) > -1 ||
el.age.toLowerCase().indexOf(input) > -1;
})
}
return value;
}
}
You can easily update this pipe for your needs.
3. Advanced search using pipe in Angular
We have already seen how the simple search works in angular, now let us check little more advanced search. You can provide a list of parameters to pipe which you want to search. Let us check with one example.
Component code
export class AppComponent {
title:String;
names:any;
constructor(){
this.title = "Angular advanced search";
this.list = [
{name:'prashobh',age:'25'},
{name:'Abraham',age:'35'},
{name:'Sam',age:'45'},
{name:'Anil',age:'15'},
{name:'Mariya',age:'24'},
{name:'Crock',age:'28'},
{name:'Ram',age:'21'},
]
this.searchableList = ['name','age']
}
}
There is no change except I have added a list "searchableList". This list we will be passing to our custom pipe, check below updated html for that.
<input type="text" [(ngModel)]="queryString" id="search" placeholder="Search to type">
<ul>
<li *ngFor="let n of list | FilterPipe: queryString : searchableList ">
{{n.name}} ({{n.age}})
</li>
</ul>
We can pass array/object/string to a customer pipe, I am not explaining those in details here. Now let us check our updated pipe.
Updated pipe
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
name: 'FilterPipe',
})
export class FilterPipe implements PipeTransform {
transform(value: any, input: string, searchableList: any) {
if (input) {
input = input.toLowerCase();
return value.filter(function (el: any) {
var isTrue = false;
for (var k in searchableList) {
if (el[searchableList[k]].toLowerCase().indexOf(input) > -1) {
isTrue = true;
}
if (isTrue) {
return el
}
}
})
}
return value;
}
}
We are done, you can simply add any parameters which you want to be searchable. You can use above plunker for your testing.
4. Search entire Array
If you want your pipe to be searched for entire array, you can use below pipe.
@Pipe({
name: 'FilterPipe'
})
export class FilterPipe implements PipeTransform {
transform(value: any, args?: any): any {
if (!value) return null;
if (!args) return value;
args = args.toLowerCase();
return value.filter(function (item: any) {
return JSON.stringify(item).toLowerCase().includes(args);
});
}
}
In this article we have discussed about doing a simple and advanced search in angular 2+ using pipe concept with different examples.
Related Info
1. Share data between components using a service file.
2. Create reusable component and share data between them.
3. Angular client side pagination.
4. Angular show more/less pagination
what's queryString?
ReplyDeleteIt is model name, any name you can add.
Deletetq for the code..Prashobh PS
ReplyDeleteI'm getting this error when try to implement search filter.
ReplyDeleteERROR
TypeError: el.toLowerCase is not a function
Stack trace:
FilterPipe.prototype.transform/<@webpack-internal:///../../../../../src/app/pipes/filter.pipe.ts:18:28
Please suggest me how to fix this issue.
Try to put a debugger in el.toLoweCase(), may be you need to write el.somename(which you want to filter) ...or right if(el && el.toLowerCase())
Deletetry el.toString.toLowerCase()
Deletetry el.toString().toLowerCase()
DeleteAmazinggggggg. Thanks a lot :)
ReplyDeleteIT WORKED LIKE A CHARM :)
ReplyDeleteCan't bind to 'ngModel' since it isn't a known property of 'input'.
ReplyDelete[ERROR ->][(ngModel)]="queryString" id="search">
Did you imported FormsModule to your module ?
Deleteimport { FormsModule } from '@angular/forms';
Check above module code for more info
thanks ... it was very useful ...
ReplyDeletethanks for this useful information...
ReplyDeletethanks a lot, no one explained it better, once more thanks a lot!
ReplyDeleteI have this problem, because this isProjectSelected is an array with objects.
ReplyDeleteCould you help me
Uncaught Error: Template parse errors:
The pipe 'FilterPipe' could not be found placeholder="Search to type"
table id="myTable" fxLayout="column"
td *ngFor ="[ERROR ->]let n of isProjectSelected() | FilterPipe: queryString " {{n.name}} td
table
d": ng:///AppModule/BudgetPlanningComponent.html@29:23
Please put your codes in the plunker and share here, so that we can look into that.
DeleteThank you I fixed it, but how it is possible when the item is founded to be selected.
DeleteGreat to hear that. For selecting you can just assign the selected value to your model. Something similar I have done for autocomplete : -http://www.angulartutorial.net/2018/03/create-angular-autocomplete-angular-25.html
DeleteI have created 2 icons into the search 1. search and 2. times how is possible when click x to reset the input search.
ReplyDeleteI guess you are asking for a way to clear the search box, you can try below code
Deleteinput type="text" [(ngModel)]="queryString" id="search" placeholder="Search to type">
img scr="/icon" *ngIf="queryString.length>0" (click)="queryString = '' " alt="clear">
Thank you, I made in another way and your code works too, how it is possible somehow when we type a name if is found to make like a click with enter that the last name is found or if is one name found in the array that name to be selected. i don't wan't to show in my search but just to be active.
Deletewhat if I want to search min and max date?
ReplyDeletefrom this date to this date
I want that kind of filter ?
is it possible ?
Yes it is possible. You can modify the pipe to read date, may be pass a flag. I don't have have a ready made code in my hand now.
Deleteit worked for me. thank you
ReplyDeleteExcellent tutorial, the best. Thank you very very much!!
ReplyDeletehow to apply the search filter entire components??????
ReplyDeletedo you have ready made code for this type of cases???? bcse i want to learn immediatly so only
ReplyDeleteThank you so much , I am new to JS and angular, this helped along.
ReplyDeleteCan you please tell me how do you know the pipe code, i mean to search thriugh whole array and all is this some js part, all the code here seems very stange to me since i am from C++ background.
pipe locator Awesome article, it was exceptionally helpful! I simply began in this and I'm becoming more acquainted with it better! Cheers, keep doing awesome!
ReplyDeleteis there a stackblitz for this. doesn't seem to work at all.
ReplyDeleteWhat is the error you are getting?
Deleteis this code works for nested result set. I have nested result set on which the search has to be performed.
ReplyDeletewill the filter work for nested result set if not can you please modify it accordingly. like
ReplyDelete{Person[firstname:manish,lastname:kumar],
employee[code:'123',description:'abc'],
id:123,
date'2023-10/16'} something like this
will it work for nested data set
ReplyDelete