Filtering in Angular MultiSelect Dropdown
31 Aug 202621 minutes to read
The MultiSelect component has built-in support for filtering data items when allowFiltering is enabled. The filter operation starts as soon as you type in the MultiSelect input.
Populate the popup with filtered items by querying the data source and passing the result to the MultiSelect via the updateData method, inside the filtering event.
The following sample shows how to query the data source and pass the filtered data to the MultiSelect through the updateData method in the filtering event.
import { NgModule } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { FormsModule, ReactiveFormsModule } from '@angular/forms'
import { MultiSelectModule } from '@syncfusion/ej2-angular-dropdowns'
import { ButtonModule } from '@syncfusion/ej2-angular-buttons'
import { Component } from '@angular/core';
import { FilteringEventArgs } from '@syncfusion/ej2-angular-dropdowns';
import { DataManager,Query } from '@syncfusion/ej2-data';
import { EmitType } from '@syncfusion/ej2-base';
@Component({
imports: [
FormsModule, ReactiveFormsModule, MultiSelectModule, ButtonModule
],
standalone: true,
selector: 'app-root',
// specifies the template string for the MultiSelect component
template: `<ejs-multiselect id='multiselectelement' [dataSource]='searchData' [fields]='fields' [allowFiltering]='true' [placeholder]='placeholder' (filtering)='onFiltering($event)'></ejs-multiselect>`
})
export class AppComponent {
constructor() {
}
// defined the array of data
public searchData: { [key: string]: Object }[] = [
{ index: "s1", country: "Alaska" }, { index: "s2", country: "California" },
{ index: "s3", country: "Florida" }, { index: "s4", country: "Georgia" }
];
// map the appropriate column
public fields: Object = { text: "country", value: "index" };
// set the placeholder to the MultiSelect input
public placeholder: string = 'Select countries';
//Bind the filter event
public onFiltering: EmitType<FilteringEventArgs> = (e: FilteringEventArgs) => {
e.preventDefaultAction = true; // Prevent the default built-in filter.
let query = new Query();
//frame the query based on search string with filter type.
query = (e.text != "") ? query.where("country", "startswith", e.text, true) : query;
//pass the filter data source, filter query to updateData method.
e.updateData(this.searchData, query);
};
}import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));Limit the minimum filter character
When filtering list items, you can set the minimum character count that triggers a remote request and fetches filtered data for the MultiSelect. This is done by manual validation within the filtering event handler.
In the following example, the remote request does not fetch the search data until the search key contains three characters.
import { NgModule } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { FormsModule, ReactiveFormsModule } from '@angular/forms'
import { MultiSelectModule } from '@syncfusion/ej2-angular-dropdowns'
import { ButtonModule } from '@syncfusion/ej2-angular-buttons'
import { Component } from '@angular/core';
import { FilteringEventArgs } from '@syncfusion/ej2-angular-dropdowns';
import { Query, DataManager, ODataV4Adaptor } from '@syncfusion/ej2-data';
import { EmitType } from '@syncfusion/ej2-base';
@Component({
imports: [
FormsModule, ReactiveFormsModule, MultiSelectModule, ButtonModule
],
standalone: true,
selector: 'app-root',
// specifies the template string for the MultiSelect component
template: `<ejs-multiselect id='multiselectelement' [dataSource]='searchData' [fields]='fields' [allowFiltering]='true' [placeholder]='placeholder' [sortOrder]='sorting' [query]='query' (filtering)='onFiltering($event)'></ejs-multiselect>`
})
export class AppComponent {
constructor() {
}
//bind the DataManager instance to dataSource property
public searchData: DataManager = new DataManager({
url: 'https://services.odata.org/V4/Northwind/Northwind.svc/Customers',
adaptor: new ODataV4Adaptor,
crossDomain: true
});
// map the appropriate column
public fields: Object = { text: 'ContactName', value: 'CustomerID' };
//bind the Query instance to query property
public query: Query = new Query().select(['ContactName', 'CustomerID']).take(7);
// set the placeholder to the MultiSelect input
public placeholder: string = 'Select customers';
//sort the resulted items
public sorting: string = 'Ascending';
//Bind the filter event
public onFiltering: EmitType<FilteringEventArgs> = (e: FilteringEventArgs) => {
e.preventDefaultAction = true; // Prevent the default built-in filter.
// load overall data when search key empty.
if(e.text == '') e.updateData(this.searchData);
else{
// restrict the remote request until search key contains 3 characters.
if (e.text.length < 3) { return; }
let query: Query = new Query().select(['ContactName', 'CustomerID']);
query = (e.text !== '') ? query.where('ContactName', 'startswith', e.text, true) : query;
e.updateData(this.searchData, query);
}
};
}import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));Change the filter type
While filtering, you can change the filter type to contains, startsWith, or endsWith for string type within the filtering event handler. You can also use the filterType property to set the default filtering criteria.
| FilterType | Description | Supported Types |
|---|---|---|
| StartsWith | Checks whether a value begins with the specified value. | String |
| EndsWith | Checks whether a value ends with the specified value. | String |
| Contains | Checks whether a value contains the specified value. | String |
In the following examples, data filtering is done with endsWith type.
import { NgModule } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { FormsModule, ReactiveFormsModule } from '@angular/forms'
import { MultiSelectModule } from '@syncfusion/ej2-angular-dropdowns'
import { ButtonModule } from '@syncfusion/ej2-angular-buttons'
import { Component } from '@angular/core';
import { FilteringEventArgs } from '@syncfusion/ej2-angular-dropdowns';
import { Query, DataManager, ODataV4Adaptor } from '@syncfusion/ej2-data';
import { EmitType } from '@syncfusion/ej2-base';
@Component({
imports: [
FormsModule, ReactiveFormsModule, MultiSelectModule, ButtonModule
],
standalone: true,
selector: 'app-root',
// specifies the template string for the MultiSelect component
template: `<ejs-multiselect id='multiselectelement' [dataSource]='searchData' [fields]='fields' [allowFiltering]='true' [placeholder]='placeholder' [sortOrder]='sorting'[query]='query' (filtering)='onFiltering($event)'></ejs-multiselect>`
})
export class AppComponent {
constructor() {
}
//bind the DataManager instance to dataSource property
public searchData: DataManager = new DataManager({
url: 'https://services.odata.org/V4/Northwind/Northwind.svc/Customers',
adaptor: new ODataV4Adaptor,
crossDomain: true
});
// map the appropriate column
public fields: Object = { text: 'ContactName', value: 'CustomerID' };
//bind the Query instance to query property
public query: Query = new Query().select(['ContactName', 'CustomerID']).take(7);
// set the placeholder to the MultiSelect input
public placeholder: string = 'Select names';
//sort the resulted items
public sorting: string = 'Ascending';
//Bind the filter event
public onFiltering: EmitType<FilteringEventArgs> = (e: FilteringEventArgs) => {
e.preventDefaultAction = true; // Prevent the default built-in filter.
// load overall data when search key empty.
if(e.text == '') e.updateData(this.searchData);
else{
let query: Query = new Query().select(['ContactName', 'CustomerID']);
// change the type of filtering
query = (e.text !== '') ? query.where('ContactName', 'endswith', e.text, true) : query;
e.updateData(this.searchData, query);
}
};
}import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));Case sensitive filtering
Data items can be filtered with or without case sensitivity using the DataManager. This is done by passing the fourth optional parameter of the where clause. The ignoreCase property can also be used to enable or disable case-sensitive filtering by default.
The following example shows how to perform case-sensitive filter.
import { NgModule } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { FormsModule, ReactiveFormsModule } from '@angular/forms'
import { MultiSelectModule } from '@syncfusion/ej2-angular-dropdowns'
import { ButtonModule } from '@syncfusion/ej2-angular-buttons'
import { Component } from '@angular/core';
import { FilteringEventArgs } from '@syncfusion/ej2-angular-dropdowns';
import { EmitType } from '@syncfusion/ej2-base';
import { Query } from '@syncfusion/ej2-data';
@Component({
imports: [
FormsModule, ReactiveFormsModule, MultiSelectModule, ButtonModule
],
standalone: true,
selector: 'app-root',
// specifies the template string for the MultiSelect component
template: `<ejs-multiselect id='multiselectelement' [dataSource]='sportsData' [fields]='fields' [allowFiltering]='true' [placeholder]='placeholder' [popupHeight]='popupHeight' [sortOrder]='sorting' (filtering)='onFiltering($event)'></ejs-multiselect>`
})
export class AppComponent {
constructor() {
}
//bind the DataManager instance to dataSource property
public sportsData: { [key: string]: Object }[] = [
{ id: 'game1', sports: 'Badminton' },
{ id: 'game2', sports: 'Football' },
{ id: 'game3', sports: 'Tennis' },
{ id: 'game4', sports: 'Golf' },
{ id: 'game5', sports: 'Hockey' }
];
// map the appropriate column
public fields: Object = { text: 'sports', value: 'id' };
// set the placeholder to the MultiSelect input
public placeholder: string = 'Select games';
//sort the resulted items
public sorting: string = 'Ascending';
//set the height of the popup element
public popupHeight: string = '250px';
//Bind the filter event
public onFiltering: EmitType<FilteringEventArgs> = (e: FilteringEventArgs) => {
e.preventDefaultAction = true; // Prevent the default built-in filter.
// load overall data when search key empty.
if(e.text == '') e.updateData(this.sportsData);
else{
let query: Query = new Query().select(['sports', 'id']);
//enable the case sensitive filtering by passing false to 4th parameter.
query = (e.text !== '') ? query.where('sports', 'startswith', e.text, false) : query;
e.updateData(this.sportsData, query);
}
};
}import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));Diacritics Filtering
MultiSelect supports diacritics filtering, which ignores the diacritics and makes it easier to filter results in lists that contain international characters when the ignoreAccent property is enabled.
In the following sample, data with diacritics is bound as the dataSource for the MultiSelect.
import { NgModule } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { FormsModule, ReactiveFormsModule } from '@angular/forms'
import { MultiSelectModule } from '@syncfusion/ej2-angular-dropdowns'
import { ButtonModule } from '@syncfusion/ej2-angular-buttons'
import { Component } from '@angular/core';
@Component({
imports: [
FormsModule, ReactiveFormsModule, MultiSelectModule, ButtonModule
],
standalone: true,
selector: 'app-root',
// specifies the template string for the DropDownList component with change event
template: `<ejs-multiselect id='diacritics' [dataSource]='data' [allowFiltering]='true' [ignoreAccent]='true' placeholder='e.g. aero'>
</ejs-multiselect>`
})
export class AppComponent {
constructor() {
}
// create local data
public data: string[] = [
'Aeróbics',
'Aeróbics en Agua',
'Aerografía',
'Aeromodelaje',
'Águilas',
'Ajedrez',
'Ala Delta',
'Álbumes de Música',
'Alusivos',
'Análisis de Escritura a Mano'];
}import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));Debounce delay
Use the debounceDelay property for filtering to set a delay, in milliseconds. This reduces the frequency of filtering as you type, enhancing performance and responsiveness for a smoother user experience. By default, a debounceDelay of 300ms is set. To disable this feature entirely, set the value to 0ms.
import { FormsModule, ReactiveFormsModule } from '@angular/forms'
import { MultiSelectModule } from '@syncfusion/ej2-angular-dropdowns'
import { ButtonModule } from '@syncfusion/ej2-angular-buttons'
import { Component } from '@angular/core';
@Component({
imports: [
FormsModule, ReactiveFormsModule, MultiSelectModule, ButtonModule
],
standalone: true,
selector: 'app-root',
// specifies the template string for the MultiSelect component with dataSource
template: `<ejs-multiselect id='multiselectelement' [dataSource]='sportsData' [placeholder]='placeholder' [allowFiltering]="true" [debounceDelay]='debounceDelay'></ejs-multiselect>`
})
export class AppComponent {
constructor() {
}
// defined the array of data
public sportsData: string[] = ['Badminton', 'Basketball', 'Cricket', 'Football', 'Golf', 'Gymnastics', 'Hockey', 'Tennis'];
// set placeholder to MultiSelect input element
public placeholder: string = 'Select games';
//set the debounceDelay
public debounceDelay: number = 500;
}import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));