A modern, feature-rich select component for Angular with react-select API compatibility
npm install angular-perfect-selectA modern, feature-rich, and fully accessible select component for Angular applications. Built with react-select API compatibility, enhanced animations, and a focus on user experience.


| Package Version | Angular Version | TypeScript Version |
|-----------------|-----------------|-------------------|
| v3.x | Angular 21+ | TypeScript 5.9+ |
| v2.x | Angular 20 | TypeScript 5.8+ |
Choose the right version for your project:
``bashFor Angular 21+ projects
npm install angular-perfect-select@^3.0.0 @angular/cdk@^21.0.0
> Note: v3.x and v2.x have feature parity. The only difference is Angular version support. If you're on Angular 20, use v2.x. When you upgrade to Angular 21, switch to v3.x.
Features
$3
- React-Select Compatible - Full API compatibility with react-select
- Modern UI - Beautiful design with smooth, enhanced animations
- Angular 21+ - Built with standalone components and signals
- Async Loading - Load options asynchronously with caching support
- Creatable Options - Allow users to create new options on the fly
- Search/Filter - Built-in search functionality with custom filter support
- Multi-Select - Support for selecting multiple options with animated tag chips
- Keyboard Navigation - Full keyboard support (Arrow keys, Enter, Escape, Tab, Backspace)
- Accessibility - ARIA labels and comprehensive screen reader support
- Forms Integration - Full support for Angular template-driven and reactive forms$3
#### v2.3.0 Features 🎉 NEW
- Fuzzy Search - Advanced search algorithm supporting acronym-style matching (e.g., 'fb' matches 'Facebook')
- Dark Mode - Automatic dark mode detection with manual override and dedicated dark theme
- Loading Skeleton - Modern shimmer skeleton UI while loading async options
- Compact Mode - Ultra-dense layout variant with reduced padding for data-heavy UIs
- Custom Tag Templates - Full control over multi-select tag rendering with ng-template
- Option Checkbox Mode - Display checkboxes next to options for better visual selection feedback
- Bulk Actions - Action buttons for performing operations on all selected options
- Option Sorting - Built-in sorting modes (alphabetical, recently used, custom comparator)
#### v2.2.0 Features
- Search Result Highlighting - Automatically highlights matching text in options with customizable colors
- Tag Overflow Management - Show "+N more" or collapsible tags when exceeding visible limit
#### v2.1.0 Features
- Drag & Drop Reordering - Reorder selected tags in multi-select mode with intuitive drag handles
- Option Pinning - Pin frequently used options to the top with persistence support
#### v2.0.0 Features
- Virtual Scrolling - Handle 10,000+ options without performance degradation using Angular CDK
- Custom Option Templates - Full control over option rendering with ng-template support
- Validation States - Visual error, warning, success, and info states with custom messages
- Advanced Keyboard Shortcuts - Ctrl+A, Ctrl+C/V, Home/End, and type-ahead navigation
- Copy/Paste Support - Copy selected values and paste comma-separated lists
- Option Tooltips - Display additional information on hover with configurable content
- Recent Selections - Show recently selected items at top with optional persistence
- Infinite Scroll - Load more options as user scrolls with pagination support
#### v1.1.0 Features
- Max Selection Limit - Limit the number of selections in multi-select mode with visual feedback
- Search Debounce - Configurable debounce delay for async loading to reduce API calls
- Min Search Length - Require minimum characters before filtering with helpful progress indicator
#### Core Features
- Select All / Deselect All - One-click selection for multi-select mode
- Option Grouping - Organize options into categories with sticky headers
- Icons in Options - Add visual elements (SVG or images) to options
- Badges in Options - Display status, roles, or categories with custom colors
- Color Themes - 7 beautiful color themes: blue, purple, green, red, orange, pink, dark
- Container Sizing - 5 physical container sizes: xs, sm, md, lg, xl
- Font Sizing - 5 font size variants: smaller (11px), small (13px), medium (14px), large (16px), larger (18px)
- Custom Styles - Inject custom styles for complete control over appearance
- Custom Render Functions -
getOptionLabel, getOptionValue, isOptionDisabled
- Flexible Options - Support for option descriptions and disabled states
- Loading States - Built-in loading indicators for sync and async operations
- RTL Support - Right-to-left language support
- Menu Positioning - Auto, top, or bottom placement with fixed positioning support
- Enhanced Animations - Smooth dropdown animations, staggered options, and tag transitions
- Modern UI - Beautiful design with enhanced shadows, backdrop blur effects, and rounded cornersInstallation
See Version Compatibility above to choose the right version for your Angular project.
`bash
npm
npm install angular-perfect-select @angular/cdkyarn
yarn add angular-perfect-select @angular/cdkpnpm
pnpm add angular-perfect-select @angular/cdk
`> ⚠️ Important: Angular CDK (
@angular/cdk) is a required peer dependency and must be installed alongside the package.Quick Start
$3
`typescript
import { Component } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { PerfectSelectComponent, SelectOption } from 'angular-perfect-select';@Component({
selector: 'app-demo',
standalone: true,
imports: [FormsModule, PerfectSelectComponent],
template: \
})
export class DemoComponent {
selectedValue: any = null; options: SelectOption[] = [
{ id: 'sl', label: 'Sri Lanka', value: 'sl' },
{ id: 'ind', label: 'India', value: 'ind' },
{ id: 'pak', label: 'Pakistan', value: 'pak' }
];
}
`$3
`typescript
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { PerfectSelectComponent } from 'angular-perfect-select';@NgModule({
imports: [
FormsModule,
PerfectSelectComponent
],
// ...
})
export class AppModule { }
`Usage Examples
$3
Enable intelligent fuzzy search for better option matching:
`typescript
[options]="options"
[enableFuzzySearch]="true"
[fuzzySearchThreshold]="0.3"
[fuzzySearchCaseSensitive]="false"
[isSearchable]="true"
placeholder="Try searching 'fb' to find 'Facebook'..."
/>
`$3
Automatic dark mode detection with system preference:
`typescript
[options]="options"
[enableAutoThemeDetection]="true"
[darkModeTheme]="'dark'"
[lightModeTheme]="'blue'"
[colorScheme]="'auto'"
placeholder="Auto dark mode..."
/>// Manual dark mode override
[options]="options"
[colorScheme]="'dark'"
placeholder="Always dark mode..."
/>
`$3
Show modern skeleton UI while loading:
`typescript
[loadOptions]="loadRemoteData"
[enableLoadingSkeleton]="true"
[skeletonItemCount]="5"
[skeletonItemHeight]="40"
[skeletonAnimationDelay]="800"
placeholder="Loading with skeleton..."
/>
`$3
Dense layout for dashboards and data grids:
`typescript
[options]="options"
[compactMode]="true"
placeholder="Compact select..."
/>
`$3
Fully customize how multi-select tags are rendered:
`typescript
[options]="options"
[isMulti]="true"
[(ngModel)]="selectedValues"
>
![]()
{{option.label}}
{{option.role}}
`$3
Display checkboxes for better visual feedback:
`typescript
[options]="options"
[isMulti]="true"
[showOptionCheckboxes]="true"
[checkboxPosition]="'left'"
[checkboxStyle]="'filled'"
placeholder="Select with checkboxes..."
/>
`$3
Add action buttons for selected options:
`typescript
// Component
bulkActions: BulkAction[] = [
{
id: 'export',
label: 'Export',
icon: '/assets/export.svg',
action: (selectedOptions) => this.exportSelected(selectedOptions)
},
{
id: 'delete',
label: 'Delete All',
action: (selectedOptions) => this.deleteSelected(selectedOptions)
}
];// Template
[options]="options"
[isMulti]="true"
[enableBulkActions]="true"
[bulkActions]="bulkActions"
[bulkActionsPosition]="'above'"
[bulkActionsLabel]="'Actions:'"
(bulkActionSelected)="onBulkAction($event)"
/>
`$3
Sort options automatically:
`typescript
// Alphabetical sorting
[options]="options"
[sortMode]="'alphabetical-asc'"
placeholder="Sorted A-Z..."
/>// Recently used sorting
[options]="options"
[sortMode]="'recently-used'"
[recentlyUsedLimit]="10"
placeholder="Recently used first..."
/>
// Custom sorting
[options]="options"
[sortMode]="'custom'"
[customSortComparator]="customSort"
placeholder="Custom sorted..."
/>
// Component
customSort = (a: SelectOption, b: SelectOption) => {
return a.priority - b.priority;
};
`$3
Highlight matching text in options during search:
`typescript
[options]="options"
[enableSearchHighlight]="true"
[searchHighlightColor]="'#ffeb3b'"
[searchHighlightTextColor]="'#000'"
[isSearchable]="true"
placeholder="Search with highlighting..."
/>
`$3
Show "+N more" when tags exceed limit:
`typescript
[options]="options"
[isMulti]="true"
[maxVisibleTags]="3"
[showMoreTagsText]="'+{count} more'"
placeholder="Select multiple..."
/>// With collapsible tags
[options]="options"
[isMulti]="true"
[maxVisibleTags]="3"
[collapsibleTags]="true"
[showAllTagsText]="'Show all'"
[showLessTagsText]="'Show less'"
placeholder="Select multiple (collapsible)..."
/>
`$3
Reorder selected tags in multi-select mode with drag-and-drop:
`typescript
[options]="options"
[isMulti]="true"
[enableDragDrop]="true"
[dragDropPlaceholder]="'Drop here'"
[dragDropAnimation]="200"
(reorder)="handleReorder($event)"
/>// In your component
handleReorder(event: SelectReorderEvent) {
console.log('Reordered from', event.previousIndex, 'to', event.currentIndex);
console.log('New order:', event.values);
}
`$3
Pin frequently used options to the top of the dropdown:
`typescript
[options]="options"
[enablePinning]="true"
[maxPinnedOptions]="3"
[persistPinnedOptions]="true"
[pinnedOptionsLabel]="'Favorites'"
(pin)="handlePin($event)"
/>// In your component
handlePin(event: SelectPinEvent) {
console.log('Option', event.option.label, event.pinned ? 'pinned' : 'unpinned');
}
`$3
Limit the number of selections in multi-select mode:
`typescript
[options]="options"
[isMulti]="true"
[maxSelectedOptions]="3"
maxSelectedMessage="You can only select up to 3 items"
[(ngModel)]="selectedValues"
>
`$3
Add debouncing to async search to reduce API calls:
`typescript
[options]="[]"
[loadOptions]="loadCountries"
[debounceTime]="500"
[(ngModel)]="selectedCountry"
>
``typescript
loadCountries = async (searchTerm: string): Promise => {
const response = await fetch( /api/countries?search=${searchTerm});
return response.json();
};
`$3
Require minimum characters before filtering options:
`typescript
[options]="largeDataset"
[minSearchLength]="3"
minSearchMessage="Please enter at least 3 characters"
[(ngModel)]="selectedValue"
>
`$3
Handle large datasets (10,000+ options) with virtual scrolling:
`typescript
[options]="hugeDataset"
[enableVirtualScroll]="true"
[virtualScrollItemSize]="40"
[(ngModel)]="selectedValue"
>
`$3
Provide custom rendering for options:
`typescript
![]()
{{option.label}}
{{option.email}}
@if (selected) {
Selected
}
`$3
Visual validation feedback for forms:
`typescript
[options]="options"
validationState="error"
validationMessage="Please select at least one option"
[(ngModel)]="selectedValue"
>
`$3
Power-user keyboard navigation:
- Ctrl/Cmd+A: Select all options (multi-select)
- Ctrl/Cmd+C: Copy selected values to clipboard
- Ctrl/Cmd+V: Paste comma-separated values (multi-select)
- Home: Jump to first option
- End: Jump to last option
- Type-ahead: Type characters to jump to matching option
`typescript
[options]="options"
[enableAdvancedKeyboard]="true"
[enableCopyPaste]="true"
[typeAheadDelay]="500"
[(ngModel)]="selectedValue"
>
`$3
Copy selected values and paste comma-separated lists:
`typescript
[options]="options"
[isMulti]="true"
[enableCopyPaste]="true"
[copyDelimiter]="', '"
[pasteDelimiter]=","
(copy)="onCopy($event)"
(paste)="onPaste($event)"
[(ngModel)]="selectedValues"
>
`$3
Show additional information on hover:
`typescript
[options]="optionsWithTooltips"
[showTooltips]="true"
[tooltipDelay]="300"
[(ngModel)]="selectedValue"
>
``typescript
// Options with tooltip property
options = [
{ id: 1, label: 'Option 1', value: 'opt1', tooltip: 'This is a helpful tooltip' },
{ id: 2, label: 'Option 2', value: 'opt2', tooltip: 'Additional information here' }
];
`$3
Display recently selected items at the top:
`typescript
[options]="options"
[showRecentSelections]="true"
[recentSelectionsLimit]="5"
[recentSelectionsLabel]="'Recently Selected'"
[enableRecentSelectionsPersistence]="true"
[(ngModel)]="selectedValue"
>
`$3
Load more options as user scrolls:
`typescript
[options]="options"
[enableInfiniteScroll]="true"
[infiniteScrollThreshold]="80"
(scrollEnd)="loadMoreOptions($event)"
[(ngModel)]="selectedValue"
>
``typescript
loadMoreOptions(event: SelectScrollEndEvent) {
// Load more data when user scrolls to 80% of the list
this.fetchMoreOptions().then(newOptions => {
this.options = [...this.options, ...newOptions];
});
}
`$3
`typescript
[options]="options"
[isMulti]="true"
placeholder="Select multiple..."
[(ngModel)]="selectedValues"
>
`$3
`typescript
[loadOptions]="loadRemoteData"
[cacheOptions]="true"
[defaultOptions]="true"
[(ngModel)]="selectedValue"
>
`$3
`typescript
[options]="options"
[isCreatable]="true"
(createOption)="onCreateOption($event)"
[(ngModel)]="selectedValue"
>
`$3
`typescript
[options]="options"
theme="purple"
selectSize="large"
containerSize="lg"
[(ngModel)]="selectedValue"
>
``For complete documentation, examples, and interactive playground, visit:
https://angular-perfect-select.ishansasika.dev
MIT © Ishan Karunaratne