ngx-st-multiselect-autocomplete
v18.0.1
Published
- [Overview](#overview) - [Installation](#installation) - [Basic Usage](#basic-usage) - [Inputs](#inputs) - [Outputs](#outputs) - [Settings Model](#settings-model) - [Usage Examples](#usage-examples) - [Best Practices](#best-practices)
Readme
Multiselect Autocomplete Component - Complete Documentation
Table of Contents
Overview
The ngx-st-multiselect-autocomplete component is a multi-select autocomplete with chip display. Features include:
- Searchable autocomplete dropdown
- Multiple selection support
- Selected items displayed as chips
- Observable-based filtering
- Custom option labels and values
- Maximum selection limit
- Clear after select option
Installation
npm install ngx-st-multiselect-autocompleteImport the module:
import { NgxStMultiselectAutocompleteModule } from 'ngx-st-multiselect-autocomplete';
@NgModule({
imports: [NgxStMultiselectAutocompleteModule]
})
export class AppModule { }Basic Usage
// Component
settings: StMultiselectAutocompleteSettingsModel<User> = {
getFilteredOptions: (search: string) => {
return this.userService.searchUsers(search);
},
getOptionLabel: (user: User) => user.name,
getValue: (user: User) => user.id,
getChipsLabel: (user: User) => user.name
};<ngx-st-multiselect-autocomplete
label="Select Users"
searchLabel="Search for users..."
[settings]="settings"
(selectedDataChanged)="onSelectionChange($event)">
</ngx-st-multiselect-autocomplete>Inputs
label
- Type:
string - Default:
'' - Description: Main label for the component.
- Example:
label="Select Users" label="Choose Tags"
searchLabel
- Type:
string - Default:
'' - Description: Placeholder text for the search input.
- Example:
searchLabel="Search for users..." searchLabel="Type to search..."
settings ⭐ (Required)
- Type:
StMultiselectAutocompleteSettingsModel<T> - Required: Yes
- Description: Configuration object that defines how to fetch and display options.
- Example:
settings: StMultiselectAutocompleteSettingsModel<User> = { getFilteredOptions: (search) => this.userService.search(search), getOptionLabel: (user) => user.name, getValue: (user) => user.id, getChipsLabel: (user) => user.name };
initSelectedData
- Type:
any[] - Default:
undefined - Description: Array of initially selected items.
- Example:
[initSelectedData]="preselectedUsers"
maxLengthSelectedData
- Type:
number | null - Default:
null - Description: Maximum number of items that can be selected. When reached, search input is disabled.
- Example:
[maxLengthSelectedData]="5" [maxLengthSelectedData]="10"
clearAfterSelect
- Type:
boolean - Default:
true - Description: Clears the search input after selecting an item.
- Example:
[clearAfterSelect]="true" [clearAfterSelect]="false"
Outputs
selectedDataChanged
- Type:
any[] - Description: Emitted whenever the selected items change (add or remove).
- Example:
(selectedDataChanged)="onSelectionChange($event)" onSelectionChange(selectedItems: any[]): void { console.log('Selected:', selectedItems); }
Settings Model
The StMultiselectAutocompleteSettingsModel<T> interface:
interface StMultiselectAutocompleteSettingsModel<T> {
// Required: Function to fetch filtered options based on search string
getFilteredOptions: (search: string) => Observable<T[]>;
// Optional: Function to get label for dropdown options
getOptionLabel?: (option: T) => string;
// Optional: Function to get value from option
getValue?: (option: T) => any;
// Optional: Function to get label for selected chips
getChipsLabel?: (option: any) => string;
}getFilteredOptions (Required)
- Type:
(search: string) => Observable<T[]> - Description: Function that returns an Observable of filtered options based on search string.
- Example:
getFilteredOptions: (search: string) => { return this.http.get<User[]>(`/api/users?search=${search}`); }
getOptionLabel (Optional)
- Type:
(option: T) => string - Description: Function to format option display in the dropdown.
- Example:
getOptionLabel: (user: User) => `${user.firstName} ${user.lastName}`
getValue (Optional)
- Type:
(option: T) => any - Description: Function to extract the value from an option.
- Example:
getValue: (user: User) => user.id
getChipsLabel (Optional)
- Type:
(option: any) => string - Description: Function to format the chip label for selected items.
- Example:
getChipsLabel: (user: User) => user.name
Usage Examples
Example 1: Basic User Selection
// Component
@Component({
selector: 'app-user-selector',
template: `
<ngx-st-multiselect-autocomplete
label="Assign Users"
searchLabel="Search users..."
[settings]="userSettings"
(selectedDataChanged)="onUsersSelected($event)">
</ngx-st-multiselect-autocomplete>
<div>
<h4>Selected Users: {{ selectedUsers.length }}</h4>
</div>
`
})
export class UserSelectorComponent {
selectedUsers: User[] = [];
userSettings: StMultiselectAutocompleteSettingsModel<User> = {
getFilteredOptions: (search: string) => {
return this.userService.searchUsers(search);
},
getOptionLabel: (user: User) => `${user.name} (${user.email})`,
getValue: (user: User) => user.id,
getChipsLabel: (user: User) => user.name
};
constructor(private userService: UserService) {}
onUsersSelected(users: User[]): void {
this.selectedUsers = users;
console.log('Selected users:', users);
}
}Example 2: Tag Selection with Limit
// Component
@Component({
selector: 'app-tag-selector',
template: `
<ngx-st-multiselect-autocomplete
label="Add Tags"
searchLabel="Search tags..."
[settings]="tagSettings"
[maxLengthSelectedData]="5"
[initSelectedData]="initialTags"
(selectedDataChanged)="onTagsChanged($event)">
</ngx-st-multiselect-autocomplete>
<p *ngIf="tags.length === 5" class="warning">
Maximum of 5 tags reached
</p>
`
})
export class TagSelectorComponent {
tags: Tag[] = [];
initialTags: Tag[] = [
{ id: 1, name: 'Angular' },
{ id: 2, name: 'TypeScript' }
];
tagSettings: StMultiselectAutocompleteSettingsModel<Tag> = {
getFilteredOptions: (search: string) => {
return this.tagService.search(search);
},
getOptionLabel: (tag: Tag) => tag.name,
getValue: (tag: Tag) => tag.id,
getChipsLabel: (tag: Tag) => tag.name
};
constructor(private tagService: TagService) {}
onTagsChanged(tags: Tag[]): void {
this.tags = tags;
}
}Example 3: Email Recipients
// Component
@Component({
selector: 'app-email-composer',
template: `
<form [formGroup]="emailForm">
<ngx-st-multiselect-autocomplete
label="To:"
searchLabel="Enter email addresses..."
[settings]="recipientSettings"
[clearAfterSelect]="true"
(selectedDataChanged)="updateRecipients($event)">
</ngx-st-multiselect-autocomplete>
<mat-form-field>
<mat-label>Subject</mat-label>
<input matInput formControlName="subject">
</mat-form-field>
<mat-form-field>
<mat-label>Message</mat-label>
<textarea matInput formControlName="message"></textarea>
</mat-form-field>
<button mat-raised-button color="primary" (click)="send()">
Send Email
</button>
</form>
`
})
export class EmailComposerComponent {
recipients: Contact[] = [];
emailForm = this.fb.group({
subject: [''],
message: ['']
});
recipientSettings: StMultiselectAutocompleteSettingsModel<Contact> = {
getFilteredOptions: (search: string) => {
return this.contactService.searchContacts(search);
},
getOptionLabel: (contact: Contact) =>
`${contact.name} <${contact.email}>`,
getValue: (contact: Contact) => contact.email,
getChipsLabel: (contact: Contact) => contact.name
};
constructor(
private fb: FormBuilder,
private contactService: ContactService
) {}
updateRecipients(contacts: Contact[]): void {
this.recipients = contacts;
}
send(): void {
const emailData = {
to: this.recipients.map(r => r.email),
subject: this.emailForm.value.subject,
message: this.emailForm.value.message
};
console.log('Sending email:', emailData);
}
}Example 4: Product Categories
// Component
@Component({
selector: 'app-product-categories',
template: `
<ngx-st-multiselect-autocomplete
label="Product Categories"
searchLabel="Search categories..."
[settings]="categorySettings"
[initSelectedData]="product.categories"
[maxLengthSelectedData]="3"
(selectedDataChanged)="onCategoriesChanged($event)">
</ngx-st-multiselect-autocomplete>
`
})
export class ProductCategoriesComponent {
product = {
name: 'Product Name',
categories: []
};
categorySettings: StMultiselectAutocompleteSettingsModel<Category> = {
getFilteredOptions: (search: string) => {
return this.categoryService.search(search).pipe(
map(categories =>
categories.filter(c => !this.isAlreadySelected(c))
)
);
},
getOptionLabel: (category: Category) => category.name,
getValue: (category: Category) => category.id,
getChipsLabel: (category: Category) => category.name
};
constructor(private categoryService: CategoryService) {}
onCategoriesChanged(categories: Category[]): void {
this.product.categories = categories;
}
isAlreadySelected(category: Category): boolean {
return this.product.categories.some(c => c.id === category.id);
}
}Example 5: Skills Selection
// Component
@Component({
selector: 'app-skills-selector',
template: `
<div class="skills-section">
<h3>Add Your Skills</h3>
<ngx-st-multiselect-autocomplete
label="Skills"
searchLabel="Type to search skills..."
[settings]="skillsSettings"
[clearAfterSelect]="true"
(selectedDataChanged)="onSkillsChanged($event)">
</ngx-st-multiselect-autocomplete>
<div class="skills-summary">
<h4>Your Skills ({{ skills.length }})</h4>
<div class="skill-levels">
<div *ngFor="let skill of skills">
{{ skill.name }}
<mat-slider [value]="skill.level" min="1" max="5"></mat-slider>
</div>
</div>
</div>
</div>
`
})
export class SkillsSelectorComponent {
skills: Skill[] = [];
skillsSettings: StMultiselectAutocompleteSettingsModel<Skill> = {
getFilteredOptions: (search: string) => {
if (!search || search.length < 2) {
return of([]);
}
return this.skillsService.searchSkills(search);
},
getOptionLabel: (skill: Skill) => skill.name,
getValue: (skill: Skill) => skill.id,
getChipsLabel: (skill: Skill) => skill.name
};
constructor(private skillsService: SkillsService) {}
onSkillsChanged(skills: Skill[]): void {
this.skills = skills.map(skill => ({
...skill,
level: skill.level || 3
}));
}
}Example 6: With Local Filtering
// Component
@Component({
selector: 'app-local-multiselect',
template: `
<ngx-st-multiselect-autocomplete
label="Select Items"
searchLabel="Search..."
[settings]="localSettings"
(selectedDataChanged)="onItemsChanged($event)">
</ngx-st-multiselect-autocomplete>
`
})
export class LocalMultiselectComponent {
allItems: Item[] = [
{ id: 1, name: 'Apple', category: 'Fruit' },
{ id: 2, name: 'Banana', category: 'Fruit' },
{ id: 3, name: 'Carrot', category: 'Vegetable' },
{ id: 4, name: 'Broccoli', category: 'Vegetable' }
];
localSettings: StMultiselectAutocompleteSettingsModel<Item> = {
getFilteredOptions: (search: string) => {
const filtered = this.allItems.filter(item =>
item.name.toLowerCase().includes(search.toLowerCase()) ||
item.category.toLowerCase().includes(search.toLowerCase())
);
return of(filtered);
},
getOptionLabel: (item: Item) => `${item.name} - ${item.category}`,
getValue: (item: Item) => item.id,
getChipsLabel: (item: Item) => item.name
};
onItemsChanged(items: Item[]): void {
console.log('Selected items:', items);
}
}Example 7: Team Members Assignment
// Component
@Component({
selector: 'app-team-assignment',
template: `
<form [formGroup]="projectForm">
<mat-form-field>
<mat-label>Project Name</mat-label>
<input matInput formControlName="name">
</mat-form-field>
<ngx-st-multiselect-autocomplete
label="Team Members"
searchLabel="Search team members..."
[settings]="membersSettings"
[initSelectedData]="project?.members"
[maxLengthSelectedData]="10"
(selectedDataChanged)="onMembersChanged($event)">
</ngx-st-multiselect-autocomplete>
<div class="team-summary">
<h4>Team Size: {{ teamMembers.length }}/10</h4>
<p>Roles:</p>
<ul>
<li *ngFor="let member of teamMembers">
{{ member.name }} - {{ member.role }}
</li>
</ul>
</div>
<button mat-raised-button color="primary" (click)="saveProject()">
Save Project
</button>
</form>
`
})
export class TeamAssignmentComponent {
teamMembers: TeamMember[] = [];
project?: Project;
projectForm = this.fb.group({
name: ['', Validators.required]
});
membersSettings: StMultiselectAutocompleteSettingsModel<TeamMember> = {
getFilteredOptions: (search: string) => {
return this.teamService.searchMembers(search).pipe(
map(members => members.filter(m => m.available))
);
},
getOptionLabel: (member: TeamMember) =>
`${member.name} - ${member.role} (${member.department})`,
getValue: (member: TeamMember) => member.id,
getChipsLabel: (member: TeamMember) =>
`${member.name} (${member.role})`
};
constructor(
private fb: FormBuilder,
private teamService: TeamService
) {}
onMembersChanged(members: TeamMember[]): void {
this.teamMembers = members;
}
saveProject(): void {
if (this.projectForm.valid && this.teamMembers.length > 0) {
const projectData = {
...this.projectForm.value,
members: this.teamMembers.map(m => m.id)
};
console.log('Saving project:', projectData);
}
}
}Best Practices
Implement efficient filtering in
getFilteredOptions:getFilteredOptions: (search: string) => { if (search.length < 2) return of([]); return this.service.search(search).pipe( debounceTime(300), distinctUntilChanged() ); }Provide clear labels:
getOptionLabel: (user) => `${user.name} (${user.email})` getChipsLabel: (user) => user.name // Shorter for chipsSet reasonable limits:
[maxLengthSelectedData]="10"Initialize with existing data:
[initSelectedData]="existingSelections"Handle the output properly:
onSelectionChange(items: any[]): void { this.validateSelection(items); this.updateForm(items); }Use type safety with generics:
settings: StMultiselectAutocompleteSettingsModel<User> = {...}
Common Use Cases
- User/Contact Selection: Assign users to tasks, projects, or groups
- Tagging: Add multiple tags to content
- Email Recipients: Select multiple email recipients
- Categories: Assign multiple categories to items
- Skills/Interests: Select multiple skills or interests
- Team Building: Assign team members to projects
Component Behavior
- Search: Type to filter options via
getFilteredOptions - Select: Click option to add it to selections
- Remove: Click X on chip to remove selection
- Clear: Input clears after selection if
clearAfterSelectis true - Limit: Input disables when
maxLengthSelectedDatais reached - Display: Selected items shown as Material chips
This documentation covers all inputs, outputs, and usage patterns for the Multiselect Autocomplete component.
