Advance Filter
By krish ghatul
let discuss filter with angular 5. I hope You know about inbuilt angular filters like date filter.
For example. (Inbuilt filters).
<h4>2. My name is {{ABC | lowercase}}< /h4>
<h4>2. Today is {{today | date}} </h4>
<h4>3. Today is {{today | date:"DD/MM/yyyy"}} /h4>
In this tutorial, We are going to learn How to build our own custom (Advance filter) with angular. We are going to use a pipe for building a custom filter, and I hope, You know about the custom pipe and how it works. If you don't know, please learn about angular pipes and how it works.
Let's take one example, employee. (Employee. ts)
export class Employee {
firstName: string;
lastName: string;
age: number;
salaryRange: string;
experienceRange: string;
companyName: string;
city: string;
education: string;
}
Suppose we are having a list of employees and we want to filter them using their skills or some attributes. For example, I want employee age<30 and education=”Graduate”. Here each time you need to create query dynamically and pass to filter employees.
How can you do that? Let's do it….
Download complete source code from: https://github.com/ghatul/Advance-Filter
Step 1: Create pipe (emp-card-filter.pipe.ts)
import {Pipe, PipeTransform} from "@angular/core";
import {Employee} from "../model/employee";
import {CardFilter} from "../model/card-filter";
@Pipe({name: 'cardfilter', pure: false})
export class EmpCardFilterPipe implements PipeTransform {
transform(array: Array<Employee>, args: CardFilter, cardObj: any): Array<any> {
if (array === null) {
return null;
}
if (args.query) {
var result: Employee[];
result = array.filter(item => eval(args.query));
cardObj.count = result.length;
return result;
}
cardObj.count = array.length;
return array;
}
}
cardfilter.ts
export class CardFilter {
education: string[] = new Array(0);
ageLimit: number;
query: any;
cardCount: any;
}
Step 2: Create Filter Component (filter.component.ts/.html/.css)
1. filter.component.html
<div><label> Card Count</label>{{CardObj.count}}
<div><label>Education</label><div *ngFor="let item of education">
<label>
<input type="checkbox" formControlName="eduction" value="{{item}}"
(change)="filterByEducation($event)">{{item}}
</label></div>
</div>
<div><label>Age</label><select formControlName="age" (change)="sortByAge($event.target.value)">
<option value="" selected></option>
<option value="{{item}}"
*ngFor="let item of age ">{{item}}
</option></select>
</div>
</div>
2.filter.component.ts
import {Component, EventEmitter, Input, OnInit, Output} from "@angular/core";
import {CardFilter} from "../../model/card-filter";
@Component({
selector: 'app-filter',
templateUrl: './filter.component.html',
styleUrls: ['./filter.component.css']
})
export class FilterComponent implements OnInit {
age = ['20', '30', '40', '45', '50', '55'];
education = ['Under Graduate', 'Graduate', 'Post Graduate'];
cardFilter: CardFilter = new CardFilter();
private queryList: string[] = new Array(0);
qeryString = '';
@Output() filterQryChange: EventEmitter<CardFilter> = new EventEmitter<CardFilter>();
@Input() CardObj: any;
filterByEducation(event: any) {
var value = event.target.value;
if (value == '') {
this.queryRemove('(args.education.indexOf(item.education) !== -1)');
}
if (event.target.checked) {
this.cardFilter.education.push(value);
} else {
var index = this.cardFilter.education.indexOf(value);
if (index > -1) {
this.cardFilter.education.splice(index, 1);
}
}
if (this.cardFilter.education.length) {
this.queryPush('(args.education.indexOf(item.education) !== -1)');
} else {
this.queryRemove('(args.education.indexOf(item.education) !== -1)');
}
this.buildFilterQuery();
}
sortByAge(value: string) {
if (value === '') {
this.queryRemove('(((args.ageLimit && item.age))&&(args.ageLimit >= item.age))');
} else if (value) {
this.cardFilter.ageLimit = Number(value);
this.queryPush('(((args.ageLimit && item.age))&&(args.ageLimit >= item.age))');
}
this.buildFilterQuery();
}
queryPush(query: string) {
if (this.queryList.indexOf(query) == -1) {
this.queryList.push(query);
}
}
queryRemove(query: string) {
var i = this.queryList.indexOf(query);
if (i != -1) {
this.queryList.splice(i, 1);
}
}
buildFilterQuery() {
var query = 'true';
for (var i = 0; i < this.queryList.length; i++) {
query = query + '&&' + this.queryList[i];
}
this.cardFilter.query = query;
this.filterQryChange.emit(this.cardFilter);
}}
queryPush -> is a function used to add a query for operation.
queryRemove -> is a function used to remove query for operation.
buildFilterQuery -> is a function used to build a final query.
Above filter, component shows you how to create a dynamic query. Each fields having its own query hence on each action you need to decide add or remove query from that list.
- EmpCardFilterPipe.ts
Role:- Custom pipe which is used to filter employee list.(Filter name cardfilter)
2. CardFilter.ts
Role:- Model(object/class) used as metadata for EmpCardFilterPipe.
3. filter.component.ts/.html/.css
Role:- Build CardFilter object having a query and other criterias.
4. employee.component.ts/.html/.css
Role:- Used to show employee card list.
Code: <ul *ngFor="let emp of empData | cardfilter:fiterObj:cardObj">
5. Employee.ts
Role:- Employee list data is a type of Employee.
Here fiterObj is a type of CardFilter. filterObj is used as metadata for cardfilter it contains all applied criterias on employee list and query.filterObj is a type of CardFilter.
cardObj is a type of {“count”:0} is used to show filtered list count.
Note: It just my idea(code) and you can edit, update, expand this code with your own concepts.
Suggestion:- Performance issue with huge data. So, use when data is less.
Download complete source code from: https://github.com/ghatul/Advance-Filter
Sr. Fullstack Developer at SA Technologies
7 年Very helpful..