Templates in Angular MultiSelect component
8 Oct 202524 minutes to read
The MultiSelect component provides comprehensive template customization options for list items, group headers, selected values, headers and footers. These templates use the Essential® JS 2 Template engine to compile and render elements with full data binding support, enabling rich UI customization for various use cases such as displaying complex data structures, creating multi-column layouts, and providing contextual information.
Item template
The content of each list item within the MultiSelect can be customized using the itemTemplate property. This template receives the data item as context, allowing access to all properties for custom rendering.
In the following sample, each list item displays data in a two-column layout to show relevant information effectively.
import { NgModule } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { FormsModule } from '@angular/forms'
import { MultiSelectModule } from '@syncfusion/ej2-angular-dropdowns'
import { Component } from '@angular/core';
import { Query, DataManager, ODataV4Adaptor } from '@syncfusion/ej2-data'
@Component({
imports: [
FormsModule,MultiSelectModule
],
standalone: true,
selector: 'app-root',
// specifies the template url path
templateUrl: 'template.html'
})
export class AppComponent {
height: any;
constructor() {
}
//bind the DataManager instance to dataSource property
public data: DataManager = new DataManager({
url: 'https://services.odata.org/V4/Northwind/Northwind.svc/',
adaptor: new ODataV4Adaptor,
crossDomain: true
});
// maps the appropriate column to fields property
public fields: Object = { text: 'FirstName', value: 'EmployeeID' };
//bind the Query instance to query property
public query: Query = new Query().from('Employees').select(['FirstName', 'City','EmployeeID']).take(6);
//set the placeholder to MultiSelect input
public text: string = "Select an employee";
//sort the result items
public sorting: string = 'Ascending';
}
<div id="wrapper" style='margin-top: 20px'>
<div id='content' style="margin: 0px auto; width:300px;">
<!-- specifies the template string for the MultiSelect component-->
<ejs-multiselect id='multiselect-template' #sample [dataSource]='data' [fields]='fields' [sortOrder]='sorting' [query]='query' [popupHeight]='height' [placeholder]='text'>
<ng-template #itemTemplate="" let-data="">
<!--set the value to itemTemplate property-->
<div><span class='name'></span><span class ='city'></span></div>
</ng-template>
</ejs-multiselect>
</div>
</div>
@import 'node_modules/@syncfusion/ej2-base/styles/material.css';
@import 'node_modules/@syncfusion/ej2-buttons/styles/material.css';
@import 'node_modules/@syncfusion/ej2-dropdowns/styles/material.css';
@import 'node_modules/@syncfusion/ej2-inputs/styles/material.css';
@import 'node_modules/@syncfusion/ej2-popups/styles/material.css';
@import 'node_modules/@syncfusion/ej2-lists/styles/material.css';
@import 'node_modules/@syncfusion/ej2-angular-base/styles/material.css';
@import 'node_modules/@syncfusion/ej2-angular-popups/styles/material.css';
@import 'node_modules/@syncfusion/ej2-angular-dropdowns/styles/material.css';
@import 'node_modules/@syncfusion/ej2-angular-buttons/styles/material.css';
.name {
float: left
}
.city {
float: right
}
Value template
The display of currently selected values in the MultiSelect input element can be customized using the valueTemplate property. This template affects only the visual representation of selected items in the input field, not the underlying component values.
In the following sample, selected values appear as combined text displaying both FirstName
and City
separated by a hyphen in the MultiSelect input field.
import { NgModule } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { FormsModule } from '@angular/forms'
import { MultiSelectModule } from '@syncfusion/ej2-angular-dropdowns'
import { Component } from '@angular/core';
import { Query, DataManager, ODataV4Adaptor } from '@syncfusion/ej2-data'
@Component({
imports: [
FormsModule,MultiSelectModule
],
standalone: true,
selector: 'app-root',
// specifies the template url path
templateUrl: 'template.html'
})
export class AppComponent {
constructor() {
}
//bind the DataManager instance to dataSource property
public data: DataManager = new DataManager({
url: 'https://services.odata.org/V4/Northwind/Northwind.svc/',
adaptor: new ODataV4Adaptor,
crossDomain: true
});
// maps the appropriate column to fields property
public fields: Object = { text: 'FirstName', value: 'EmployeeID' };
//bind the Query instance to query property
public query: Query = new Query().from('Employees').select(['FirstName', 'City','EmployeeID']).take(6);
//set the placeholder to MultiSelect input
public text: string = "Select an employee";
//sort the result items
public sorting: string = 'Ascending';
public box : string = 'box';
}
<div id="wrapper">
<div id='content' style="margin: 0px auto; width:300px;">
<!-- specifies the template string for the MultiSelect component-->
<ejs-multiselect id='multiselectelement' #sample [dataSource]='data' [fields]='fields' [mode]='box' [sortOrder]='sorting' [placeholder]='text' [query]='query'>
<ng-template #itemTemplate="" let-data="">
<!--set the value to itemTemplate property-->
<div><span class='name'></span><span class ='city'></span></div>
</ng-template>
<ng-template #valueTemplate="" let-data="">
<!--set the value to valueTemplate property-->
<span> - </span>
</ng-template>
</ejs-multiselect>
</div>
</div>
@import 'node_modules/@syncfusion/ej2-base/styles/material.css';
@import 'node_modules/@syncfusion/ej2-buttons/styles/material.css';
@import 'node_modules/@syncfusion/ej2-dropdowns/styles/material.css';
@import 'node_modules/@syncfusion/ej2-inputs/styles/material.css';
@import 'node_modules/@syncfusion/ej2-popups/styles/material.css';
@import 'node_modules/@syncfusion/ej2-lists/styles/material.css';
@import 'node_modules/@syncfusion/ej2-angular-base/styles/material.css';
@import 'node_modules/@syncfusion/ej2-angular-popups/styles/material.css';
@import 'node_modules/@syncfusion/ej2-angular-dropdowns/styles/material.css';
@import 'node_modules/@syncfusion/ej2-angular-buttons/styles/material.css';
.name {
float: left
}
.city {
float: right
}
Group template
The group header titles that categorize sub-items can be customized using the groupTemplate property. This template applies to both inline and floating group header styles and receives the group data as context.
In the following sample, employees are grouped by city with custom group header styling.
import { NgModule } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { FormsModule } from '@angular/forms'
import { MultiSelectModule } from '@syncfusion/ej2-angular-dropdowns'
import { Component } from '@angular/core';
import { Query, Predicate, DataManager, ODataV4Adaptor } from '@syncfusion/ej2-data'
@Component({
imports: [
FormsModule,MultiSelectModule
],
standalone: true,
selector: 'app-root',
// specifies the template url path
templateUrl: 'template.html'
})
export class AppComponent {
constructor() {
}
//bind the DataManager instance to dataSource property
public data: DataManager = new DataManager({
url: 'https://services.odata.org/V4/Northwind/Northwind.svc/',
adaptor: new ODataV4Adaptor,
crossDomain: true
});
// form predicate to fetch the grouped data
public groupPredicate = new Predicate('City', 'equal','london').or('City','equal','seattle');
// maps the appropriate column to fields property
public fields: Object = { text: 'FirstName', value: 'EmployeeID', groupBy:'City' };
//bind the Query instance to query property
public query: Query = new Query().from('Employees').select(['FirstName', 'City','EmployeeID']).take(6).where(this.groupPredicate);
//set the placeholder to MultiSelect input
public text: string = "Select an employee";
//sort the result items
public sorting: string = 'Ascending';
}
<div id="wrapper" style='margin-top: 20px'>
<div id='content' style="margin: 0px auto; width:250px;">
<!-- specifies the template string for the MultiSelect component-->
<ejs-multiselect id='multiselectelement' #sample [dataSource]='data' [fields]='fields' [sortOrder]='sorting' [placeholder]='text' [query]='query'>
<ng-template #groupTemplate="" let-data="">
<!--set the value to groupTemplate property-->
<strong></strong>
</ng-template>
</ejs-multiselect>
</div>
</div>
@import 'node_modules/@syncfusion/ej2-base/styles/material.css';
@import 'node_modules/@syncfusion/ej2-buttons/styles/material.css';
@import 'node_modules/@syncfusion/ej2-dropdowns/styles/material.css';
@import 'node_modules/@syncfusion/ej2-inputs/styles/material.css';
@import 'node_modules/@syncfusion/ej2-popups/styles/material.css';
@import 'node_modules/@syncfusion/ej2-lists/styles/material.css';
@import 'node_modules/@syncfusion/ej2-angular-base/styles/material.css';
@import 'node_modules/@syncfusion/ej2-angular-popups/styles/material.css';
@import 'node_modules/@syncfusion/ej2-angular-dropdowns/styles/material.css';
@import 'node_modules/@syncfusion/ej2-angular-buttons/styles/material.css';
Header template
The header element appears at the top of the popup list and can display custom content using the headerTemplate property. This template is useful for adding titles, instructions, or column headers for structured data display.
In the following sample, the header and list items are designed as a two-column grid layout with appropriate column headers.
import { NgModule } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { FormsModule } from '@angular/forms'
import { MultiSelectModule } from '@syncfusion/ej2-angular-dropdowns'
import { Component } from '@angular/core';
import { Query, DataManager, ODataV4Adaptor } from '@syncfusion/ej2-data';
@Component({
imports: [
FormsModule,MultiSelectModule
],
standalone: true,
selector: 'app-root',
// specifies the template url path
templateUrl: 'template.html'
})
export class AppComponent {
constructor() {
}
//bind the DataManager instance to dataSource property
public data: DataManager = new DataManager({
url: 'https://services.odata.org/V4/Northwind/Northwind.svc/',
adaptor: new ODataV4Adaptor,
crossDomain: true
});
// maps the appropriate column to fields property
public fields: Object = { text: 'FirstName', value: 'EmployeeID' };
//bind the Query instance to query property
public query: Query = new Query().from('Employees').select(['FirstName', 'City','EmployeeID']).take(6);
//set the placeholder to MultiSelect input
public text: string = "Select an employee";
//sort the result items
public sorting: string = 'Ascending';
}
<div id="wrapper" style='margin-top: 20px'>
<div id='content' style="margin: 0px auto; width:250px;">
<!-- specifies the template string for the MultiSelect component-->
<ejs-multiselect id='multiselectelement' #sample [dataSource]='data' [fields]='fields' [sortOrder]='sorting' [placeholder]='text' [query]='query'>
<ng-template #itemTemplate="" let-data="">
<!--set the value to itemTemplate property-->
<span class='item'><span class='name'> </span><span class ='city'></span></span>
</ng-template>
<ng-template #headerTemplate="" let-data="">
<!--set the value to headerTemplate property-->
<span class='head'><span class='name'>Name</span><span class='city'>City</span></span>
</ng-template>
</ejs-multiselect>
</div>
</div>
@import 'node_modules/@syncfusion/ej2-base/styles/material.css';
@import 'node_modules/@syncfusion/ej2-buttons/styles/material.css';
@import 'node_modules/@syncfusion/ej2-dropdowns/styles/material.css';
@import 'node_modules/@syncfusion/ej2-inputs/styles/material.css';
@import 'node_modules/@syncfusion/ej2-popups/styles/material.css';
@import 'node_modules/@syncfusion/ej2-lists/styles/material.css';
@import 'node_modules/@syncfusion/ej2-angular-base/styles/material.css';
@import 'node_modules/@syncfusion/ej2-angular-popups/styles/material.css';
@import 'node_modules/@syncfusion/ej2-angular-dropdowns/styles/material.css';
@import 'node_modules/@syncfusion/ej2-angular-buttons/styles/material.css';
.head, .item{
display: table;
width:100%;
margin:auto;
}
.head{
height: 40px;
font-size:15px;
font-weight:600;
}
.name, .city{
display: table-cell;
vertical-align: middle;
width: 50%;
}
.head .name {
text-indent: 16px;
}
.head .city {
text-indent: 10px;
}
Footer template
The footer element appears at the bottom of the popup list and can contain summary information or additional actions using the footerTemplate property. Common uses include displaying item counts, action buttons, or additional navigation options.
In the following sample, the footer displays the total count of available list items in the MultiSelect.
import { NgModule } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { FormsModule } from '@angular/forms'
import { MultiSelectModule } from '@syncfusion/ej2-angular-dropdowns'
import { Component } from '@angular/core';
@Component({
imports: [
FormsModule,MultiSelectModule
],
standalone: true,
selector: 'app-root',
// specifies the template url path
templateUrl: 'template.html'
})
export class AppComponent {
// create a object for MultiSelect
constructor() {
}
// defined the array of data
public data: Object[] = ['Badminton', 'Basketball', 'Cricket', 'Golf'];
// set placeholder text to MultiSelect input element
public text: string = 'Select a game';
}
<div id="wrapper" style='margin-top: 20px'>
<div id='content' style="margin: 0px auto; width:250px;">
<!-- specifies the template string for the MultiSelect component-->
<ejs-multiselect id='multiselectelement' #samples [dataSource]='data' [placeholder]='text' [footerTemplate]='footerTemplate'>
<ng-template #footerTemplate="" let-data="">
<!--set the value to footerTemplate property-->
<span class='foot'> Total list item: 4</span>
</ng-template>
</ejs-multiselect>
</div>
</div>
@import 'node_modules/@syncfusion/ej2-base/styles/material.css';
@import 'node_modules/@syncfusion/ej2-buttons/styles/material.css';
@import 'node_modules/@syncfusion/ej2-dropdowns/styles/material.css';
@import 'node_modules/@syncfusion/ej2-inputs/styles/material.css';
@import 'node_modules/@syncfusion/ej2-popups/styles/material.css';
@import 'node_modules/@syncfusion/ej2-lists/styles/material.css';
@import 'node_modules/@syncfusion/ej2-angular-base/styles/material.css';
@import 'node_modules/@syncfusion/ej2-angular-popups/styles/material.css';
@import 'node_modules/@syncfusion/ej2-angular-dropdowns/styles/material.css';
.foot{
text-indent: 1.2em;
display: block;
font-size: 15px;
line-height: 40px;
border-top: 1px solid #e0e0e0;
}
No records template
The MultiSelect supports custom design for the popup list content when no data is available or no search matches are found using the noRecordsTemplate property. This template enhances user experience by providing clear feedback about data availability.
In the following sample, the popup displays a custom notification when no data is available.
import { NgModule } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { FormsModule } from '@angular/forms'
import { MultiSelectModule } from '@syncfusion/ej2-angular-dropdowns'
import { Component } from '@angular/core';
@Component({
imports: [
FormsModule,MultiSelectModule
],
standalone: true,
selector: 'app-root',
// specifies the template string for the MultiSelect component
template: `<ejs-multiselect id='multiselectelement' [dataSource]='data' placeholder='Find a item'>
<ng-template #noRecordsTemplate>
<span class='norecord'> NO DATA AVAILABLE</span>
</ng-template>
</ejs-multiselect>`
})
export class AppComponent {
// defined the empty array data
public data: string[] = [];
}
@import 'node_modules/@syncfusion/ej2-base/styles/material.css';
@import 'node_modules/@syncfusion/ej2-buttons/styles/material.css';
@import 'node_modules/@syncfusion/ej2-dropdowns/styles/material.css';
@import 'node_modules/@syncfusion/ej2-inputs/styles/material.css';
@import 'node_modules/@syncfusion/ej2-popups/styles/material.css';
@import 'node_modules/@syncfusion/ej2-lists/styles/material.css';
@import 'node_modules/@syncfusion/ej2-angular-base/styles/material.css';
@import 'node_modules/@syncfusion/ej2-angular-popups/styles/material.css';
@import 'node_modules/@syncfusion/ej2-angular-dropdowns/styles/material.css';
@import 'node_modules/@syncfusion/ej2-angular-buttons/styles/material.css';
.norecord:before{
content: '\e7c3';
font-family: 'e-icons';
font-size: 18px;
margin-left: -25px;
margin-top: -3px;
position: absolute;
}
.action-failure:before{
content: '\e7c4';
font-family: 'e-icons';
font-size: 18px;
margin-top: -4px;
position: absolute;
margin-left: -25px;
}
Action failure template
The popup list content can be customized when data fetch requests fail at the remote server using the actionFailureTemplate property. This template provides users with appropriate error messaging and potential recovery actions.
In the following sample, the MultiSelect displays a custom error notification when data fetch requests fail.
import { NgModule } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { FormsModule } from '@angular/forms'
import { MultiSelectModule } from '@syncfusion/ej2-angular-dropdowns'
import { Component } from '@angular/core';
//import data manager related classes
import { Query, DataManager, ODataV4Adaptor } from '@syncfusion/ej2-data';
@Component({
imports: [
FormsModule,MultiSelectModule
],
standalone: true,
selector: 'app-root',
// specifies the template string for the MultiSelect component
template: `<ejs-multiselect id='multiselectelement' [dataSource]='data' [query]='query'
[fields]='fields' placeholder='Find an employee'>
<ng-template #actionFailureTemplate>
<span class='action-failure'> Data fetch get fails</span>
</ng-template>
</ejs-multiselect>`
})
export class AppComponent {
//bind the data manager instance to dataSource property
public data: DataManager = new DataManager({
// Here, use the wrong url to display the action failure template
url: 'https://services.odata.org/V4/Northwind/Northwind.svcs/',
adaptor: new ODataV4Adaptor,
crossDomain: true
});
//bind the Query instance to query property
public query: Query = new Query().from('Employees').select(['FirstName']).take(6);
// maps the appropriate column to fields property
public fields: Object = { text: 'FirstName', value: 'EmployeeID' };
}
@import 'node_modules/@syncfusion/ej2-base/styles/material.css';
@import 'node_modules/@syncfusion/ej2-buttons/styles/material.css';
@import 'node_modules/@syncfusion/ej2-dropdowns/styles/material.css';
@import 'node_modules/@syncfusion/ej2-inputs/styles/material.css';
@import 'node_modules/@syncfusion/ej2-popups/styles/material.css';
@import 'node_modules/@syncfusion/ej2-lists/styles/material.css';
@import 'node_modules/@syncfusion/ej2-angular-base/styles/material.css';
@import 'node_modules/@syncfusion/ej2-angular-popups/styles/material.css';
@import 'node_modules/@syncfusion/ej2-angular-dropdowns/styles/material.css';
@import 'node_modules/@syncfusion/ej2-angular-buttons/styles/material.css';
.norecord:before{
content: '\e7c3';
font-family: 'e-icons';
font-size: 18px;
margin-left: -25px;
margin-top: -3px;
position: absolute;
}
.action-failure:before{
content: '\e7c4';
font-family: 'e-icons';
font-size: 18px;
margin-top: -4px;
position: absolute;
margin-left: -25px;
}