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;
}

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;
}

See Also