0
# Core Select Component
1
2
The `NgSelectComponent` is the main component providing comprehensive select functionality including single-select, multi-select, autocomplete, virtual scrolling, and extensive customization options.
3
4
## Type Definitions
5
6
```typescript { .api }
7
/**
8
* Function type for comparing items for selection state
9
*/
10
export type CompareWithFn = (a: any, b: any) => boolean;
11
12
/**
13
* Function type for adding custom tags
14
*/
15
export type AddTagFn = (term: string) => any | Promise<any>;
16
17
/**
18
* Function type for generating group values from grouped items
19
*/
20
export type GroupValueFn = (key: string | any, children: any[]) => string | any;
21
22
/**
23
* Dropdown positioning options
24
*/
25
export type DropdownPosition = 'top' | 'right' | 'bottom' | 'left' | 'auto';
26
```
27
28
## Capabilities
29
30
### NgSelectComponent
31
32
Main select component implementing Angular's `ControlValueAccessor` for seamless form integration.
33
34
```typescript { .api }
35
/**
36
* Main select component with support for single/multi-select, autocomplete, virtual scrolling
37
* Implements ControlValueAccessor for reactive and template-driven forms integration
38
*/
39
@Component({
40
selector: 'ng-select',
41
providers: [
42
{
43
provide: NG_VALUE_ACCESSOR,
44
useExisting: forwardRef(() => NgSelectComponent),
45
multi: true
46
}
47
]
48
})
49
export class NgSelectComponent implements ControlValueAccessor, OnInit, OnDestroy, OnChanges, AfterViewInit {
50
// Data binding properties
51
/** Array of items to display in dropdown */
52
@Input() items: any[];
53
/** Property name to use for display labels (e.g., 'name') */
54
@Input() bindLabel: string;
55
/** Property name to use for values (e.g., 'id') */
56
@Input() bindValue: string;
57
/** Function to compare items for selection state */
58
@Input() compareWith: CompareWithFn;
59
60
// Selection mode properties
61
/** Enable multiple selection mode */
62
@Input() multiple: boolean = false;
63
/** Enable adding custom tags/items */
64
@Input() addTag: boolean | AddTagFn = false;
65
/** Maximum number of items that can be selected */
66
@Input() maxSelectedItems: number;
67
68
// Display properties
69
/** Placeholder text when no selection */
70
@Input() placeholder: string = '';
71
/** Keep placeholder visible even when item is selected */
72
@Input() fixedPlaceholder: boolean = false;
73
/** Text shown when no matching results found */
74
@Input() notFoundText: string = 'No items found';
75
/** Text shown when search term is required */
76
@Input() typeToSearchText: string = 'Type to search';
77
/** Text shown when adding new tags */
78
@Input() addTagText: string = 'Add item';
79
/** Text shown during loading state */
80
@Input() loadingText: string = 'Loading...';
81
/** Text shown for clear all action */
82
@Input() clearAllText: string = 'Clear all';
83
/** Visual appearance style */
84
@Input() appearance: string;
85
86
// Behavior properties
87
/** Enable search/filter functionality */
88
@Input() searchable: boolean = true;
89
/** Show clear button when item is selected */
90
@Input() clearable: boolean = true;
91
/** Component is in loading state */
92
@Input() loading: boolean = false;
93
/** Component is disabled */
94
@Input() disabled: boolean = false;
95
/** Component is readonly */
96
@Input() readonly: boolean = false;
97
/** Close dropdown after making selection */
98
@Input() closeOnSelect: boolean = true;
99
/** Hide selected items from dropdown options */
100
@Input() hideSelected: boolean = false;
101
/** Select marked item when Tab key is pressed */
102
@Input() selectOnTab: boolean = false;
103
/** Open dropdown when Enter key is pressed */
104
@Input() openOnEnter: boolean;
105
/** Clear selection when backspace is pressed */
106
@Input() clearOnBackspace: boolean = true;
107
/** Prevent dropdown toggle on right mouse click */
108
@Input() preventToggleOnRightClick: boolean = false;
109
/** Mark first item as highlighted by default */
110
@Input() markFirst: boolean = true;
111
/** Allow search while composing (IME) */
112
@Input() searchWhileComposing: boolean = true;
113
/** Minimum search term length before searching */
114
@Input() minTermLength: number = 0;
115
/** Allow editing the search term */
116
@Input() editableSearchTerm: boolean = false;
117
118
// Dropdown positioning properties
119
/** Control dropdown open state */
120
@Input() isOpen: boolean;
121
/** Position of dropdown panel */
122
@Input() dropdownPosition: DropdownPosition = 'auto';
123
/** Element to append dropdown to (CSS selector or 'body') */
124
@Input() appendTo: string;
125
126
// Virtual scrolling properties
127
/** Enable virtual scrolling for large datasets */
128
@Input() virtualScroll: boolean = false;
129
/** Number of items to buffer when virtual scrolling */
130
@Input() bufferAmount: number = 4;
131
132
// Grouping properties
133
/** Group items by property name or function */
134
@Input() groupBy: string | ((item: any) => any);
135
/** Function to generate group values */
136
@Input() groupValue: GroupValueFn;
137
/** Allow selecting entire groups */
138
@Input() selectableGroup: boolean = false;
139
/** Include groups as part of the model */
140
@Input() selectableGroupAsModel: boolean = true;
141
/** Clear search term when adding new item */
142
@Input() get clearSearchOnAdd(): boolean { /* computed */ };
143
/** Allow deselecting items by clicking them again */
144
@Input() get deselectOnClick(): boolean { /* computed */ };
145
146
// Advanced properties
147
/** Custom search function */
148
@Input() searchFn: (term: string, item: any) => boolean;
149
/** TrackBy function for ngFor performance */
150
@Input() trackByFn: (index: number, item: any) => any;
151
/** Custom keydown handler function */
152
@Input() keyDownFn: (event: KeyboardEvent) => boolean;
153
/** Observable for typeahead functionality */
154
@Input() typeahead: Subject<string>;
155
/** Additional CSS classes */
156
@Input() ngClass: any;
157
/** Tab index for accessibility */
158
@Input() tabIndex: number;
159
/** Label ID for accessibility */
160
@Input() labelForId: string;
161
/** Additional input element attributes */
162
@Input() inputAttrs: {[key: string]: string} = {};
163
/** Enable tab focus on clear button */
164
@Input() tabFocusOnClearButton: boolean; // signal input
165
166
// Accessibility properties
167
/** ARIA label for the component */
168
@Input() ariaLabel: string | undefined;
169
/** ARIA labelledby attribute for accessibility */
170
@Input() ariaLabelledBy: string;
171
/** ARIA label for the dropdown */
172
@Input() ariaLabelDropdown: string = 'Options List';
173
174
// Events
175
/** Emitted when component loses focus */
176
@Output() blur: EventEmitter<any> = new EventEmitter();
177
/** Emitted when component gains focus */
178
@Output() focus: EventEmitter<any> = new EventEmitter();
179
/** Emitted when selection changes */
180
@Output() change: EventEmitter<any> = new EventEmitter();
181
/** Emitted when dropdown opens */
182
@Output() open: EventEmitter<void> = new EventEmitter();
183
/** Emitted when dropdown closes */
184
@Output() close: EventEmitter<void> = new EventEmitter();
185
/** Emitted when search term changes */
186
@Output() search: EventEmitter<{term: string, items: any[]}> = new EventEmitter();
187
/** Emitted when selection is cleared */
188
@Output() clear: EventEmitter<void> = new EventEmitter();
189
/** Emitted when item is added (including tags) */
190
@Output() add: EventEmitter<any> = new EventEmitter();
191
/** Emitted when item is removed */
192
@Output() remove: EventEmitter<any> = new EventEmitter();
193
/** Emitted during virtual scroll */
194
@Output() scroll: EventEmitter<{start: number, end: number}> = new EventEmitter();
195
/** Emitted when scrolled to end of list */
196
@Output() scrollToEnd: EventEmitter<void> = new EventEmitter();
197
198
// Public Properties
199
/** Array of currently selected items as NgOption objects */
200
selectedItems: NgOption[];
201
/** Array of raw selected values */
202
selectedValues: any[];
203
/** Whether the component currently has any selected values */
204
hasValue: boolean;
205
/** Current position of the dropdown panel */
206
currentPanelPosition: DropdownPosition;
207
/** Whether to show the add tag option */
208
showAddTag: boolean;
209
210
// Public Methods
211
/**
212
* Toggle the dropdown open/closed state
213
*/
214
toggle(): void;
215
216
/**
217
* Clear all selected items from the model
218
*/
219
clearModel(): void;
220
221
/**
222
* Select a specific item
223
* @param item - The NgOption to select
224
*/
225
select(item: NgOption): void;
226
227
/**
228
* Unselect a specific item
229
* @param item - The NgOption to unselect
230
*/
231
unselect(item: NgOption): void;
232
233
/**
234
* Toggle selection state of an item
235
* @param item - The NgOption to toggle
236
*/
237
toggleItem(item: NgOption): void;
238
239
/**
240
* Select the current tag being created
241
*/
242
selectTag(): void;
243
244
/**
245
* Determine if the clear button should be shown
246
* @returns true if clear button should be visible
247
*/
248
showClear(): boolean;
249
250
/**
251
* Focus on the clear button element
252
*/
253
focusOnClear(): void;
254
255
/**
256
* Determine if "no items found" message should be shown
257
* @returns true if no items message should be visible
258
*/
259
showNoItemsFound(): boolean;
260
261
/**
262
* Determine if "type to search" message should be shown
263
* @returns true if type to search message should be visible
264
*/
265
showTypeToSearch(): boolean;
266
267
/**
268
* Filter items based on search term
269
* @param term - The search term to filter by
270
*/
271
filter(term: string): void;
272
273
/**
274
* Handle composition start event (for IME input)
275
*/
276
onCompositionStart(): void;
277
278
/**
279
* Handle composition end event (for IME input)
280
* @param term - The composed search term
281
*/
282
onCompositionEnd(term: string): void;
283
284
/**
285
* Trigger change detection manually
286
*/
287
detectChanges(): void;
288
289
/**
290
* Clear a specific item from selection
291
* @param item - The item to clear
292
*/
293
clearItem(item: any): void;
294
295
/**
296
* TrackBy function for ngFor performance optimization
297
* @param index - The index of the item
298
* @param item - The NgOption item
299
* @returns Unique identifier for tracking
300
*/
301
trackByOption(index: number, item: NgOption): any;
302
}
303
```
304
305
**Usage Examples:**
306
307
```typescript
308
import { Component } from '@angular/core';
309
import { NgSelectComponent, NgOptionComponent } from '@ng-select/ng-select';
310
311
// Basic single select
312
@Component({
313
selector: 'app-basic-select',
314
standalone: true,
315
imports: [NgSelectComponent, NgOptionComponent],
316
template: `
317
<ng-select [(ngModel)]="selectedUser" bindLabel="name" bindValue="id">
318
<ng-option *ngFor="let user of users" [value]="user.id">
319
{{ user.name }}
320
</ng-option>
321
</ng-select>
322
`
323
})
324
export class BasicSelectComponent {
325
selectedUser: number;
326
users = [
327
{id: 1, name: 'Alice'},
328
{id: 2, name: 'Bob'}
329
];
330
}
331
332
// Multi-select with custom templates
333
@Component({
334
template: `
335
<ng-select
336
[(ngModel)]="selectedUsers"
337
[multiple]="true"
338
[closeOnSelect]="false"
339
[clearable]="true"
340
placeholder="Select users">
341
342
<ng-option *ngFor="let user of users" [value]="user">
343
<img [src]="user.avatar" width="20"> {{ user.name }}
344
</ng-option>
345
346
<ng-label-tmp let-item="item" let-clear="clear">
347
<span class="ng-value-label">{{ item.name }}</span>
348
<span class="ng-value-icon right" (click)="clear(item)">×</span>
349
</ng-label-tmp>
350
</ng-select>
351
`
352
})
353
export class MultiSelectComponent {
354
selectedUsers: any[] = [];
355
users = [
356
{id: 1, name: 'Alice', avatar: 'alice.jpg'},
357
{id: 2, name: 'Bob', avatar: 'bob.jpg'}
358
];
359
}
360
361
// Virtual scrolling for large datasets
362
@Component({
363
template: `
364
<ng-select
365
[(ngModel)]="selectedItems"
366
[items]="largeDataset"
367
bindLabel="name"
368
bindValue="id"
369
[virtualScroll]="true"
370
[bufferAmount]="20"
371
placeholder="Search in 10,000 items...">
372
</ng-select>
373
`
374
})
375
export class VirtualScrollComponent {
376
selectedItems: any[];
377
largeDataset = Array.from({length: 10000}, (_, i) => ({
378
id: i,
379
name: `Item ${i + 1}`
380
}));
381
}
382
```
383
384
## Host Bindings and CSS Classes
385
386
The NgSelectComponent automatically applies CSS classes and attributes through @HostBinding decorators:
387
388
```typescript { .api }
389
/**
390
* CSS classes automatically applied by the component:
391
* - 'ng-select': Base component class
392
* - 'ng-select-single': Applied when multiple=false
393
* - 'ng-select-multiple': Applied when multiple=true
394
* - 'ng-select-searchable': Applied when searchable=true
395
* - 'ng-select-clearable': Applied when clearable=true
396
* - 'ng-select-opened': Applied when dropdown is open
397
* - 'ng-select-disabled': Applied when disabled=true
398
* - 'ng-select-focused': Applied when component has focus
399
* - 'ng-select-loading': Applied when loading=true
400
* - 'ng-select-readonly': Applied when readonly=true
401
* - 'ng-select-filtered': Applied when items are filtered
402
*
403
* Attributes:
404
* - 'role': Set to 'combobox' for accessibility
405
* - 'aria-expanded': Reflects dropdown open state
406
* - 'aria-haspopup': Set to 'listbox'
407
* - 'tabindex': Controlled by tabIndex input
408
*/
409
```
410
411
## Advanced Usage Examples
412
413
**Custom Search and Tag Management:**
414
415
```typescript
416
@Component({
417
template: `
418
<ng-select
419
[(ngModel)]="selectedItems"
420
[items]="filteredItems"
421
[addTag]="addTagFn"
422
[clearSearchOnAdd]="true"
423
[deselectOnClick]="true"
424
[editableSearchTerm]="true"
425
[searchWhileComposing]="false"
426
bindLabel="name"
427
bindValue="id"
428
placeholder="Search or add new items...">
429
</ng-select>
430
`
431
})
432
export class AdvancedSelectComponent {
433
selectedItems: any[] = [];
434
allItems = [
435
{id: 1, name: 'Existing Item 1'},
436
{id: 2, name: 'Existing Item 2'}
437
];
438
439
get filteredItems() {
440
// Custom filtering logic
441
return this.allItems;
442
}
443
444
addTagFn = (term: string) => {
445
return { id: Date.now(), name: term, isNew: true };
446
};
447
}
448
```
449
450
**Accessibility and Keyboard Navigation:**
451
452
```typescript
453
@Component({
454
template: `
455
<ng-select
456
[(ngModel)]="selected"
457
[items]="items"
458
[keyDownFn]="customKeyHandler"
459
[tabFocusOnClearButton]="true"
460
[ariaLabel]="'Select your preferred option'"
461
[ariaLabelDropdown]="'Available options list'"
462
bindLabel="label"
463
bindValue="value">
464
</ng-select>
465
`
466
})
467
export class AccessibleSelectComponent {
468
selected: any;
469
items = [
470
{value: 'option1', label: 'First Option'},
471
{value: 'option2', label: 'Second Option'}
472
];
473
474
customKeyHandler = (event: KeyboardEvent): boolean => {
475
// Custom keyboard handling
476
if (event.key === 'F2') {
477
// Custom behavior for F2 key
478
return false; // Prevent default
479
}
480
return true; // Allow default behavior
481
};
482
}
483
```
484
485
**Programmatic Control:**
486
487
```typescript
488
@Component({
489
template: `
490
<ng-select #selectRef [(ngModel)]="selected" [items]="items" bindLabel="name">
491
</ng-select>
492
493
<button (click)="toggleDropdown()">Toggle Dropdown</button>
494
<button (click)="clearAll()">Clear All</button>
495
<button (click)="selectFirst()">Select First Item</button>
496
<button (click)="focusClear()" [disabled]="!selectRef.showClear()">Focus Clear</button>
497
498
<div>
499
Selected Items: {{ selectRef.selectedItems?.length || 0 }}
500
Has Value: {{ selectRef.hasValue }}
501
Current Position: {{ selectRef.currentPanelPosition }}
502
</div>
503
`
504
})
505
export class ProgrammaticControlComponent {
506
@ViewChild('selectRef') selectComponent: NgSelectComponent;
507
508
selected: any;
509
items = [
510
{id: 1, name: 'Item 1'},
511
{id: 2, name: 'Item 2'},
512
{id: 3, name: 'Item 3'}
513
];
514
515
toggleDropdown() {
516
this.selectComponent.toggle();
517
}
518
519
clearAll() {
520
this.selectComponent.clearModel();
521
}
522
523
selectFirst() {
524
if (this.items.length > 0) {
525
this.selectComponent.select(this.items[0]);
526
}
527
}
528
529
focusClear() {
530
this.selectComponent.focusOnClear();
531
}
532
}
533
```
534
535
### NgOptionComponent
536
537
Individual option component for dropdown items.
538
539
```typescript { .api }
540
/**
541
* Component representing an individual option in the dropdown
542
*/
543
@Component({
544
selector: 'ng-option'
545
})
546
export class NgOptionComponent {
547
/** Value of this option */
548
@Input() value: any;
549
/** Whether this option is disabled */
550
@Input() disabled: boolean = false;
551
}
552
```
553
554
**Usage Example:**
555
556
```typescript
557
@Component({
558
template: `
559
<ng-select [(ngModel)]="selected">
560
<ng-option value="option1">Option 1</ng-option>
561
<ng-option value="option2" [disabled]="true">Option 2 (Disabled)</ng-option>
562
<ng-option value="option3">Option 3</ng-option>
563
</ng-select>
564
`
565
})
566
export class OptionsComponent {
567
selected: string;
568
}
569
```
570
571
### NgDropdownPanelComponent
572
573
Dropdown panel container component handling the display and positioning of options.
574
575
```typescript { .api }
576
/**
577
* Dropdown panel container component
578
*/
579
@Component({
580
selector: 'ng-dropdown-panel'
581
})
582
export class NgDropdownPanelComponent implements OnInit, OnDestroy, OnChanges, AfterViewInit {
583
/** Items to display in the panel */
584
@Input() items: NgOption[];
585
/** Currently marked/highlighted item */
586
@Input() markedItem: NgOption;
587
/** Position of the panel relative to select */
588
@Input() position: DropdownPosition = 'auto';
589
/** Element to append panel to */
590
@Input() appendTo: string;
591
/** Buffer amount for virtual scrolling */
592
@Input() bufferAmount: number = 4;
593
/** Enable virtual scrolling */
594
@Input() virtualScroll: boolean = false;
595
/** Template for panel header */
596
@Input() headerTemplate: TemplateRef<any>;
597
/** Template for panel footer */
598
@Input() footerTemplate: TemplateRef<any>;
599
/** Current filter/search value */
600
@Input() filterValue: string;
601
602
/** Emitted when panel items are updated */
603
@Output() update: EventEmitter<any[]> = new EventEmitter();
604
/** Emitted during scrolling */
605
@Output() scroll: EventEmitter<{start: number, end: number}> = new EventEmitter();
606
/** Emitted when scrolled to end */
607
@Output() scrollToEnd: EventEmitter<void> = new EventEmitter();
608
/** Emitted when clicked outside panel */
609
@Output() outsideClick: EventEmitter<void> = new EventEmitter();
610
}
611
```