MultiSelectMultiSelect is used to select multiple items from a collection.
Documentation
CDK
Virtual Scrolling enabled MultiSelect depends on @angular/cdk's ScrollingModule so begin with installing CDK if not already installed.
npm install @angular/cdk --save
Import
import {MultiSelectModule} from 'primeng/multiselect';
Getting Started
MultiSelect requires a value to bind and a collection of options. There are two alternatives of how to define the options property; one way is providing a collection of SelectItem instances whereas other way is providing an array of arbitrary objects along with the optionLabel property to specify the field name of the option. SelectItem API is designed to have more control on how the options are displayed such as grouping and disabling however in most cases an arbitrary object collection will suffice. Example below demonstrates both cases.
<p-multiSelect [options]="cities1" [(ngModel)]="selectedCities1"></p-multiSelect>
<p-multiSelect [options]="cities2" [(ngModel)]="selectedCities2" optionLabel="name"></p-multiSelect>
import {SelectItem} from 'primeng/api';
interface City {
name: string,
code: string
}
export class MyModel {
cities1: SelectItem[];
cities2: City[];
selectedCities1: City[];
selectedCities2: City[];
constructor() {
//SelectItem API with label-value pairs
this.cities1 = [
{label:'New York', value:{id:1, name: 'New York', code: 'NY'}},
{label:'Rome', value:{id:2, name: 'Rome', code: 'RM'}},
{label:'London', value:{id:3, name: 'London', code: 'LDN'}},
{label:'Istanbul', value:{id:4, name: 'Istanbul', code: 'IST'}},
{label:'Paris', value:{id:5, name: 'Paris', code: 'PRS'}}
];
//An array of cities
this.cities2 = [
{name: 'New York', code: 'NY'},
{name: 'Rome', code: 'RM'},
{name: 'London', code: 'LDN'},
{name: 'Istanbul', code: 'IST'},
{name: 'Paris', code: 'PRS'}
];
}
}
Model Driven Forms
MultiSelect can be used in a model driven form as well.
<p-multiSelect [options]="cities" formControlName="selectedCities"></p-multiSelect>
Disabled Options
Particular options can be prevented from selection using the disabled property of SelectItem API.
Templating
Label of a selectitem is displayed by default next to the checkbox in the overlay panel and it is possible to customize the content using templating. The ngTemplate receives the selectitem as the implicit variable.
In addition selectedItems template can be used to customize the selected values display instead of the default comma separated list.
<p-multiSelect [options]="cars" [(ngModel)]="selectedCars2" [panelStyle]="{minWidth:'12em'}">
<ng-template let-selectedCars pTemplate="selectedItems">
<span *ngFor="let selectedCar of selectedCars">{{car.brand}}</span>
</ng-template>
<ng-template let-car let-i="index" pTemplate="item">
{{i}}
<img src="assets/showcase/images/demo/car/{{car.label}}.png" style="width:24px;display:inline-block;vertical-align:middle"/>
<div style="font-size:14px;float:right;margin-top:4px">{{car.label}}</div>
</ng-template>
</p-multiSelect>
<p>Selected Cars: {{selectedCars2}}</p>
Filtering
Options can be filtered using an input field in the overlay by enabling the filter property. By default filtering is done against label of the SelectItem and filterBy property is available to choose one or more properties of the SelectItem API.
<p-multiSelect [options]="cities" [(ngModel)]="selectedCities" [filter]="true"></p-multiSelect>
<p-multiSelect [options]="cities" [(ngModel)]="selectedCities" [filter]="true" filterBy="label,value.name"></p-multiSelect>
Change Detection
MultiSelect detects changes to options and selected values using setters so when changing your model, prefer creating a new array reference instead of manipulating an existing array.
Header and Footer
p-header and p-footer elements can be used display custom content inside the header and footer sections.
<p-multiSelect [options]="cities" formControlName="selectedCities">
<p-header>
//Header content
</p-header>
<p-footer>
//Footer content
</p-footer>
</p-multiSelect>
Virtual Scrolling
VirtualScrolling is an efficient way of rendering the options by displaying a small subset of data in the viewport at any time. When dealing with huge number of options, it is suggested to enable VirtualScrolling to avoid performance issues. Usage is simple as setting virtualScroll property to true and defining itemSize to specify the height of an item.
<p-multiSelect [options]="cities" formControlName="selectedCities" [virtualScroll]="true" itemSize="30"></p-multiSelect>
Animation Configuration
Transition of the open and hide animations can be customized using the showTransitionOptions and hideTransitionOptions properties, example below disables the animations altogether.
<p-multiSelect [options]="cities" formControlName="selectedCities" [showTransitionOptions]="'0ms'" [hideTransitionOptions]="'0ms'"></p-multiSelect>
Properties
Name | Type | Default | Description |
---|---|---|---|
options | array | null | An array of objects to display as the available options. |
optionLabel | string | null | Name of the label field of an option when an arbitrary objects instead of SelectItems are used as options. |
disabled | boolean | false | When present, it specifies that the element should be disabled. |
readonly | boolean | false | When present, it specifies that the component cannot be edited. |
filter | boolean | true | When specified, displays an input field to filter the items on keyup. |
filterBy | string | label | When filtering is enabled, filterBy decides which field or fields (comma separated) to search against. |
filterPlaceHolder | string | null | Defines placeholder of the filter input. |
defaultLabel | string | Choose | Label to display when there are no selections. |
appendTo | any | null | Target element to attach the overlay, valid values are "body" or a local ng-template variable of another element. |
style | object | null | Inline style of the element. |
styleClass | string | null | Style class of the element. |
panelStyle | object | null | Inline style of the overlay panel. |
panelStyleClass | string | null | Style class of the overlay panel. |
scrollHeight | string | 200px | Height of the viewport in pixels, a scrollbar is defined if height of list exceeds this value. |
overlayVisible | boolean | false | Specifies the visibility of the options panel. |
tabindex | number | null | Index of the element in tabbing order. |
dataKey | string | null | A property to uniquely identify a value in options. |
name | string | null | Name of the input element. |
inputId | string | null | Identifier of the focus input to match a label defined for the component. |
displaySelectedLabel | boolean | true | Whether to show labels of selected item labels or use default label. |
maxSelectedLabels | number | 3 | Decides how many selected item labels to show at most. |
selectedItemsLabel | string | {0} items selected | Label to display after exceeding max selected labels. |
showToggleAll | boolean | true | Whether to show the checkbox at header to toggle all items at once. |
resetFilterOnHide | boolean | false | Clears the filter value when hiding the dropdown. |
dropdownIcon | string | pi pi-chevron-down | Icon class of the dropdown icon. |
showHeader | boolean | true | Whether to show the header. |
selectionLimit | number | null | Number of maximum options that can be selected. |
baseZIndex | number | 0 | Base zIndex value to use in layering. |
autoZIndex | boolean | true | Whether to automatically manage layering. |
showTransitionOptions | string | 225ms ease-out | Transition options of the show animation. |
hideTransitionOptions | string | 195ms ease-in | Transition options of the hide animation. |
itemSize | number | null | Height of an item in the list for VirtualScrolling. |
virtualScroll | boolean | false | Whether the data should be loaded on demand during scroll. |
ariaFilterLabel | string | null | Defines a string that labels the filter input. |
Events
Name | Parameters | Description |
---|---|---|
onClick | event: Click event | Callback to invoke when component is clicked. |
onChange | event.originalEvent: browser event event.value: Current selected values event.itemValue: Toggled item value | Callback to invoke when value changes. |
onFocus | event.originalEvent: browser event | Callback to invoke when multiselect receives focus. |
onBlur | event.originalEvent: browser event | Callback to invoke when multiselect loses focus. |
onPanelShow | - | Callback to invoke when overlay panel becomes visible. |
onPanelHide | - | Callback to invoke when overlay panel becomes hidden. |
Styling
Following is the list of structural style classes, for theming classes visit theming page.
Name | Element |
---|---|
ui-multiselect | Container element. |
ui-multiselect-label-container | Container of the label to display selected items. |
ui-multiselect-label | Label to display selected items. |
ui-multiselect-trigger | Dropdown button. |
ui-multiselect-filter-container | Container of filter input. |
ui-multiselect-panel | Overlay panel for items. |
ui-multiselect-items | List container of items. |
ui-multiselect-item | An item in the list. |
ui-multiselect-open | Container element when overlay is visible. |
Dependencies
Angular CDK.
Source
<h3 class="first">Basic</h3>
<p-multiSelect [options]="cars" [(ngModel)]="selectedCars1" [panelStyle]="{minWidth:'12em'}"></p-multiSelect>
<p>Selected Cars: {{selectedCars1}}</p>
<h3>Template</h3>
<p-multiSelect [options]="cars" [(ngModel)]="selectedCars2" [panelStyle]="{minWidth:'12em'}">
<ng-template let-value pTemplate="selectedItems">
<div *ngFor="let val of value" class="ui-multiselected-item-token ui-corner-all">
<img src="assets/showcase/images/demo/car/{{val}}.png" style="width:20px;vertical-align:middle;margin-right:.5em" />
<span>{{val}}</span>
</div>
<span *ngIf="!value || value.length === 0" class="ui-multiselected-empty-token ui-corner-all">Choose</span>
</ng-template>
<ng-template let-car pTemplate="item">
<img src="assets/showcase/images/demo/car/{{car.label}}.png" style="width:24px;display:inline-block;vertical-align:middle"/>
<div style="font-size:14px;float:right;margin-top:4px">{{car.label}}</div>
</ng-template>
</p-multiSelect>
<p>Selected Cars: {{selectedCars2}}</p>
<h3>Virtual Scroll (10000 Items)</h3>
<p-multiSelect [options]="items" [(ngModel)]="item" [panelStyle]="{minWidth:'12em'}" [virtualScroll]="true" [itemSize]="34" [filter]="false"></p-multiSelect>
@Component({
templateUrl: './multiselectdemo.html',
styles: [`
:host ::ng-deep .ui-multiselected-item-token,
:host ::ng-deep .ui-multiselected-empty-token {
padding: 2px 4px;
margin: 0 0.286em 0 0;
display: inline-block;
vertical-align:middle;
height: 1.857em;
}
:host ::ng-deep .ui-multiselected-item-token {
background: #007ad9;
color: #ffffff;
}
:host ::ng-deep .ui-multiselected-empty-token {
background: #d95f00;
color: #ffffff;
}
`]
})
export class MultiSelectDemo {
cars: SelectItem[];
selectedCars1: string[] = [];
selectedCars2: string[] = [];
items: SelectItem[];
item: string;
constructor() {
this.cars = [
{label: 'Audi', value: 'Audi'},
{label: 'BMW', value: 'BMW'},
{label: 'Fiat', value: 'Fiat'},
{label: 'Ford', value: 'Ford'},
{label: 'Honda', value: 'Honda'},
{label: 'Jaguar', value: 'Jaguar'},
{label: 'Mercedes', value: 'Mercedes'},
{label: 'Renault', value: 'Renault'},
{label: 'VW', value: 'VW'},
{label: 'Volvo', value: 'Volvo'},
];
this.items = [];
for (let i = 0; i < 10000; i++) {
this.items.push({label: 'Item ' + i, value: 'Item ' + i});
}
}
}