VUI Multi Select

A powerful, feature-rich multi-select dropdown component with search, filtering, and extensive customization options.

Angular 20+ Reactive Forms TypeScript Searchable Filterable

✨ Key Features

🔍

Advanced Search

Built-in search functionality with real-time filtering and remote data support.

Select All/None

Convenient select all and deselect all functionality for bulk operations.

🎨

Highly Customizable

Extensive configuration options for appearance, behavior, and functionality.

📦 Installation

Install via npm

npm install @vui/multi-select

Import in your module

import { VuiMultiselect } from '@vui/multi-select';

@Component({
  standalone: true,
  imports: [VuiMultiselect],
  // ...
})

⚡ Quick Start

Small Dataset (< 100 options)

const basicSettings = {
  singleSelection: false,
  idField: 'id',
  textField: 'name',
  selectAllText: 'Select All',
  unSelectAllText: 'Clear All',
  itemsShowLimit: 3,
  allowSearchFilter: false
};

Medium Dataset (100-1000 options)

const mediumSettings = {
  singleSelection: false,
  idField: 'id',
  textField: 'name',
  allowSearchFilter: true,
  searchPlaceholderText: 'Search...',
  itemsShowLimit: 5,
  enableCheckAll: true
};

Large Dataset (1000+ options)

const largeSettings = {
  singleSelection: false,
  idField: 'id',
  textField: 'name',
  allowSearchFilter: true,
  lazyLoading: true,
  virtualScrolling: true,
  itemHeight: 35,
  limitSelection: 20
};

🎯 Use Cases & Examples

Basic Multi-Selection

Perfect for simple multi-select dropdowns with basic validation.

<ng-multiselect-dropdown [data]="fruits" [(ngModel)]="selectedFruits"></ng-multiselect-dropdown>

Form Integration

Seamless integration with Angular reactive forms and validation.

<ng-multiselect-dropdown [formControl]="categoriesControl" [data]="categories"></ng-multiselect-dropdown>

Search & Filter

Built-in search functionality for large datasets.

<ng-multiselect-dropdown [data]="cities" [settings]="{allowSearchFilter: true}"></ng-multiselect-dropdown>

Grouped Options

Organize options into logical groups with validation.

<ng-multiselect-dropdown [data]="employees" [settings]="{groupBy: 'department'}"></ng-multiselect-dropdown>

🚀 Basic Usage

Simple Multi Select

Live Demo

Click the dropdown to see the interactive multi-select in action.

Implementation

@Component({
  standalone: true,
  imports: [ReactiveFormsModule, VuiMultiselect],
  template: `
    <form [formGroup]="myForm">
      <ng-vui-multiselect
        formControlName="selectedTech"
        [data]="technologies"
        [MultiSelectSettings]="dropdownSettings"
        [placeholderText]="'Select technologies...'"
        (onFilterChange)="onSearchChange($event)">
      </ng-vui-multiselect>
    </form>
  `
})
export class MyComponent {
  myForm = this.fb.group({
    selectedTech: [[]]
  });

  technologies = [
    { id: 1, name: 'Angular' },
    { id: 2, name: 'React' },
    { id: 3, name: 'Vue.js' },
    { id: 4, name: 'Svelte' }
  ];

  dropdownSettings: MultiSelectSettings = {
    singleSelection: false,
    idField: 'id',
    textField: 'name',
    selectAllText: 'Select All',
    unSelectAllText: 'Clear All',
    allowSearchFilter: true,
    closeDropDownOnSelection: false
  };

  constructor(private fb: FormBuilder) {}

  onSearchChange(searchText: string): void {
    // Handle search/filter logic
  }
}

⚡ Advanced Examples

Remote Data Search

Server-Side Search Demo

export class RemoteSearchComponent {
  cities$ = new BehaviorSubject<any[]>([]);
  searchTerm$ = new Subject<string>();

  remoteSettings: MultiSelectSettings = {
    singleSelection: false,
    idField: 'id',
    textField: 'name',
    allowSearchFilter: true,
    allowRemoteDataSearch: true,
    closeDropDownOnSelection: false,
    searchPlaceholderText: 'Search cities...',
    noDataAvailablePlaceholderText: 'No cities found'
  };

  ngOnInit(): void {
    // Debounced search with remote API
    this.searchTerm$.pipe(
      debounceTime(300),
      distinctUntilChanged(),
      switchMap(term => this.searchCities(term))
    ).subscribe(cities => {
      this.cities$.next(cities);
    });
  }

  onSearchChange(searchText: string): void {
    this.searchTerm$.next(searchText);
  }

  private searchCities(term: string): Observable<any[]> {
    return this.httpClient.get<any[]>(`/api/cities?search=${term}`);
  }
}

Custom Styling & Validation

export class StyledMultiSelectComponent {
  form = this.fb.group({
    requiredField: [[], Validators.required],
    limitedField: [[], [this.maxSelectionValidator(3)]]
  });

  customSettings: MultiSelectSettings = {
    singleSelection: false,
    idField: 'value',
    textField: 'label',
    selectAllText: '✓ Select All Items',
    unSelectAllText: '✗ Clear Selection',
    allowSearchFilter: true,
    searchPlaceholderText: '🔍 Type to search...',
    
    // Limit selections
    limitSelection: 3,
    
    // Custom display
    primaryKey: 'value',
    labelKey: 'label',
    
    // Behavior
    enableCheckAll: true,
    showSelectedItemsAtTop: true,
    groupByKey: 'category',
    
    // Appearance
    itemsShowLimit: 2,
    allowRemoteDataSearch: false,
    closeDropDownOnSelection: false,
    disabled: false,
    
    // Badge styling
    badgeShowLimit: 5,
    classes: 'custom-dropdown-class'
  };

  // Custom validator for maximum selections
  maxSelectionValidator(max: number): ValidatorFn {
    return (control: AbstractControl): ValidationErrors | null => {
      if (control.value && control.value.length > max) {
        return { maxSelection: { max, actual: control.value.length } };
      }
      return null;
    };
  }

  // Get error message for display
  getErrorMessage(fieldName: string): string {
    const field = this.form.get(fieldName);
    if (field?.errors?.['required']) {
      return 'This field is required';
    }
    if (field?.errors?.['maxSelection']) {
      const error = field.errors['maxSelection'];
      return `Maximum ${error.max} selections allowed`;
    }
    return '';
  }
}

📚 API Reference

MultiSelectSettings Interface

Property Type Default Description
singleSelection boolean false Enable single selection mode
idField string 'id' Field name for unique identifier
textField string 'text' Field name for display text
allowSearchFilter boolean false Enable search functionality
limitSelection number -1 Limit maximum selections (-1 for unlimited)
selectAllText string 'Select All' Text for select all option
allowRemoteDataSearch boolean false Enable remote data search

Component Events

Event Type Description
onFilterChange string Emitted when search filter changes
onDropDownClose void Emitted when dropdown closes
onSelect any Emitted when item is selected