ngx-st-search-selects
v18.0.1
Published
- [Overview](#overview) - [Installation](#installation) - [Basic Usage](#basic-usage) - [Inputs](#inputs) - [Outputs](#outputs) - [Usage Examples](#usage-examples) - [Best Practices](#best-practices)
Downloads
310
Readme
Search Select Component - Complete Documentation
Table of Contents
Overview
The ngx-st-search-select component is a searchable dropdown select with virtual scrolling support. Features include:
- Searchable dropdown with autocomplete
- Virtual scrolling for large datasets
- Custom option labels from multiple fields
- Flexible filtering by multiple fields
- Angular Forms integration (model or FormControl)
- Empty option support
- Disabled state
Installation
npm install ngx-st-search-selectsImport the module:
import { NgxStSearchSelectsModule } from 'ngx-st-search-selects';
@NgModule({
imports: [NgxStSearchSelectsModule]
})
export class AppModule { }Basic Usage
With ngModel
<ngx-st-search-select
selectLabel="Select User"
optionValueField="id"
optionLabelFields="firstName,lastName"
filteredByFields="firstName,lastName,email"
[options]="users"
[(model)]="selectedUserId">
</ngx-st-search-select>With FormControl
// Component
userControl = new FormControl(null);<ngx-st-search-select
selectLabel="Select User"
optionValueField="id"
optionLabelFields="firstName,lastName"
selectBindType="control"
[selectFormControl]="userControl"
[options]="users">
</ngx-st-search-select>Inputs
selectLabel
- Type:
string - Default:
undefined - Description: Label text displayed above the select.
- Example:
selectLabel="Select User" selectLabel="Choose Category"
optionValueField
- Type:
string - Default:
undefined - Description: Property name to use as the value for options.
- Example:
optionValueField="id" optionValueField="code"
optionLabelFields
- Type:
string - Default:
undefined - Description: Comma-separated list of properties to display in the dropdown. Fields are concatenated with spaces.
- Example:
optionLabelFields="name" optionLabelFields="firstName,lastName" optionLabelFields="code,name,description"
filteredByFields
- Type:
string - Default:
undefined - Description: Comma-separated list of properties to search through when filtering. If not provided, uses default filter method.
- Example:
filteredByFields="name" filteredByFields="firstName,lastName,email" filteredByFields="code,name,description,category"
model
- Type:
model signal - Default:
undefined - Description: Two-way binding model for the selected value.
- Example:
[(model)]="selectedValue"
modelChange
- Type:
(e: any) => void - Default:
undefined - Description: Custom change handler function. Alternative to using the output.
- Example:
onModelChange = (value: any) => { console.log('Changed:', value); }[modelChange]="onModelChange"
selectFormControl
- Type:
FormControl - Default:
undefined - Description: FormControl to bind when using
selectBindType="control". - Example:
userControl = new FormControl(null);[selectFormControl]="userControl"
required
- Type:
boolean - Default:
false - Description: Makes the select required (adds asterisk to label).
- Example:
[required]="true"
selectBindType
- Type:
'model' | 'control' - Default:
'model' - Description: Type of binding to use.
'model': Use withmodelinput'control': Use withselectFormControlinput
- Example:
selectBindType="model" selectBindType="control"
searchLabel
- Type:
string - Default:
'Search' - Description: Placeholder text for the search input.
- Example:
searchLabel="Search users..." searchLabel="Type to filter..."
showEmptyOption
- Type:
boolean - Default:
true - Description: Shows an empty option at the top of the list (for clearing selection).
- Example:
[showEmptyOption]="false"
useVirtualScrollOptions
- Type:
boolean - Default:
false - Description: Enables virtual scrolling for better performance with large datasets.
- Example:
[useVirtualScrollOptions]="true"
options
- Type:
any[] - Default:
[] - Description: Array of options to display in the dropdown.
- Example:
users = [ { id: 1, firstName: 'John', lastName: 'Doe', email: '[email protected]' }, { id: 2, firstName: 'Jane', lastName: 'Smith', email: '[email protected]' } ];[options]="users"
disabled
- Type:
boolean - Default:
false - Description: Disables the select dropdown.
- Example:
[disabled]="isReadOnly" [disabled]="true"
Outputs
selectDataChanged
- Type:
any - Description: Emitted when the selected value changes. Contains the selected option object.
- Example:
(selectDataChanged)="onSelectionChange($event)" onSelectionChange(selected: any): void { console.log('Selected:', selected); }
Usage Examples
Example 1: Basic User Selection
// Component
@Component({
selector: 'app-user-select',
template: `
<ngx-st-search-select
selectLabel="Select User"
searchLabel="Search users..."
optionValueField="id"
optionLabelFields="firstName,lastName"
filteredByFields="firstName,lastName,email"
[options]="users"
[(model)]="selectedUserId"
(selectDataChanged)="onUserSelected($event)">
</ngx-st-search-select>
<p *ngIf="selectedUser">
Selected: {{ selectedUser.firstName }} {{ selectedUser.lastName }}
</p>
`
})
export class UserSelectComponent {
selectedUserId: number;
selectedUser: User;
users: User[] = [
{ id: 1, firstName: 'John', lastName: 'Doe', email: '[email protected]' },
{ id: 2, firstName: 'Jane', lastName: 'Smith', email: '[email protected]' },
{ id: 3, firstName: 'Bob', lastName: 'Johnson', email: '[email protected]' }
];
onUserSelected(user: User): void {
this.selectedUser = user;
console.log('User selected:', user);
}
}Example 2: With FormControl and Validation
// Component
@Component({
selector: 'app-form-select',
template: `
<form [formGroup]="myForm">
<ngx-st-search-select
selectLabel="Category"
searchLabel="Search categories..."
optionValueField="id"
optionLabelFields="name"
filteredByFields="name,code"
selectBindType="control"
[selectFormControl]="myForm.get('categoryId')"
[options]="categories"
[required]="true">
</ngx-st-search-select>
<mat-error *ngIf="myForm.get('categoryId')?.hasError('required')">
Category is required
</mat-error>
<button [disabled]="myForm.invalid" (click)="submit()">
Submit
</button>
</form>
`
})
export class FormSelectComponent {
categories = [
{ id: 1, name: 'Electronics', code: 'ELEC' },
{ id: 2, name: 'Clothing', code: 'CLTH' },
{ id: 3, name: 'Food', code: 'FOOD' }
];
myForm = this.fb.group({
categoryId: [null, Validators.required]
});
constructor(private fb: FormBuilder) {}
submit(): void {
if (this.myForm.valid) {
console.log('Form data:', this.myForm.value);
}
}
}Example 3: Country/State Selection
// Component
@Component({
selector: 'app-location-select',
template: `
<div class="location-selectors">
<ngx-st-search-select
selectLabel="Country"
searchLabel="Search countries..."
optionValueField="code"
optionLabelFields="name"
filteredByFields="name,code"
[options]="countries"
[(model)]="selectedCountry"
(selectDataChanged)="onCountryChange($event)">
</ngx-st-search-select>
<ngx-st-search-select
*ngIf="selectedCountry"
selectLabel="State/Province"
searchLabel="Search states..."
optionValueField="code"
optionLabelFields="name"
filteredByFields="name,code"
[options]="states"
[(model)]="selectedState">
</ngx-st-search-select>
</div>
`
})
export class LocationSelectComponent {
selectedCountry: string;
selectedState: string;
countries = [
{ code: 'US', name: 'United States' },
{ code: 'CA', name: 'Canada' },
{ code: 'UK', name: 'United Kingdom' }
];
states: any[] = [];
private statesByCountry = {
'US': [
{ code: 'CA', name: 'California' },
{ code: 'NY', name: 'New York' },
{ code: 'TX', name: 'Texas' }
],
'CA': [
{ code: 'ON', name: 'Ontario' },
{ code: 'QC', name: 'Quebec' },
{ code: 'BC', name: 'British Columbia' }
]
};
onCountryChange(country: any): void {
this.selectedState = null;
this.states = this.statesByCountry[country.code] || [];
}
}Example 4: Product Selection with Multiple Display Fields
// Component
@Component({
selector: 'app-product-select',
template: `
<ngx-st-search-select
selectLabel="Select Product"
searchLabel="Search products..."
optionValueField="id"
optionLabelFields="code,name,category"
filteredByFields="code,name,category,manufacturer"
[options]="products"
[(model)]="selectedProductId"
(selectDataChanged)="onProductSelected($event)">
</ngx-st-search-select>
<div *ngIf="selectedProduct" class="product-details">
<h3>{{ selectedProduct.name }}</h3>
<p>Code: {{ selectedProduct.code }}</p>
<p>Price: {{ selectedProduct.price | currency }}</p>
</div>
`
})
export class ProductSelectComponent {
selectedProductId: number;
selectedProduct: Product;
products: Product[] = [
{
id: 1,
code: 'PROD-001',
name: 'Widget Pro',
category: 'Tools',
manufacturer: 'Acme Corp',
price: 99.99
},
{
id: 2,
code: 'PROD-002',
name: 'Super Gadget',
category: 'Electronics',
manufacturer: 'Tech Inc',
price: 149.99
}
];
onProductSelected(product: Product): void {
this.selectedProduct = product;
}
}Example 5: Virtual Scrolling for Large Datasets
// Component
@Component({
selector: 'app-large-select',
template: `
<ngx-st-search-select
selectLabel="Select Item"
searchLabel="Search from 10,000 items..."
optionValueField="id"
optionLabelFields="name"
filteredByFields="name,description"
[options]="largeDataset"
[useVirtualScrollOptions]="true"
[(model)]="selectedId">
</ngx-st-search-select>
`
})
export class LargeSelectComponent implements OnInit {
selectedId: number;
largeDataset: any[] = [];
ngOnInit(): void {
// Generate 10,000 items
this.largeDataset = Array.from({ length: 10000 }, (_, i) => ({
id: i + 1,
name: `Item ${i + 1}`,
description: `Description for item ${i + 1}`
}));
}
}Example 6: Dynamic Options Loading
// Component
@Component({
selector: 'app-dynamic-select',
template: `
<ngx-st-search-select
selectLabel="Select Department"
searchLabel="Search departments..."
optionValueField="id"
optionLabelFields="name"
filteredByFields="name,code"
[options]="departments"
[disabled]="loading"
[(model)]="selectedDepartmentId"
(selectDataChanged)="onDepartmentChange($event)">
</ngx-st-search-select>
<mat-spinner *ngIf="loading" diameter="30"></mat-spinner>
`
})
export class DynamicSelectComponent implements OnInit {
selectedDepartmentId: number;
departments: Department[] = [];
loading = false;
constructor(private departmentService: DepartmentService) {}
ngOnInit(): void {
this.loadDepartments();
}
loadDepartments(): void {
this.loading = true;
this.departmentService.getAll().subscribe(
departments => {
this.departments = departments;
this.loading = false;
},
error => {
console.error('Error loading departments:', error);
this.loading = false;
}
);
}
onDepartmentChange(department: Department): void {
console.log('Department selected:', department);
}
}Example 7: Without Empty Option
// Component
@Component({
selector: 'app-required-select',
template: `
<ngx-st-search-select
selectLabel="Status"
optionValueField="id"
optionLabelFields="name"
[options]="statuses"
[showEmptyOption]="false"
[required]="true"
[(model)]="selectedStatus">
</ngx-st-search-select>
`
})
export class RequiredSelectComponent implements OnInit {
selectedStatus: number;
statuses = [
{ id: 1, name: 'Active' },
{ id: 2, name: 'Inactive' },
{ id: 3, name: 'Pending' }
];
ngOnInit(): void {
// Set default value
this.selectedStatus = 1;
}
}Example 8: Cascading Selects
// Component
@Component({
selector: 'app-cascading-select',
template: `
<form [formGroup]="form">
<ngx-st-search-select
selectLabel="Category"
optionValueField="id"
optionLabelFields="name"
selectBindType="control"
[selectFormControl]="form.get('categoryId')"
[options]="categories"
(selectDataChanged)="onCategoryChange($event)">
</ngx-st-search-select>
<ngx-st-search-select
selectLabel="Subcategory"
optionValueField="id"
optionLabelFields="name"
selectBindType="control"
[selectFormControl]="form.get('subcategoryId')"
[options]="subcategories"
[disabled]="!form.get('categoryId')?.value"
(selectDataChanged)="onSubcategoryChange($event)">
</ngx-st-search-select>
<ngx-st-search-select
selectLabel="Product"
optionValueField="id"
optionLabelFields="name"
selectBindType="control"
[selectFormControl]="form.get('productId')"
[options]="products"
[disabled]="!form.get('subcategoryId')?.value">
</ngx-st-search-select>
</form>
`
})
export class CascadingSelectComponent {
categories = [...];
subcategories: any[] = [];
products: any[] = [];
form = this.fb.group({
categoryId: [null],
subcategoryId: [null],
productId: [null]
});
constructor(private fb: FormBuilder) {}
onCategoryChange(category: any): void {
this.form.patchValue({ subcategoryId: null, productId: null });
this.loadSubcategories(category.id);
}
onSubcategoryChange(subcategory: any): void {
this.form.patchValue({ productId: null });
this.loadProducts(subcategory.id);
}
loadSubcategories(categoryId: number): void {
// Load subcategories
}
loadProducts(subcategoryId: number): void {
// Load products
}
}Best Practices
Specify search fields for better filtering:
filteredByFields="name,code,description"Use virtual scrolling for large datasets:
[useVirtualScrollOptions]="true"Provide clear labels:
selectLabel="Select User" searchLabel="Search by name or email..."Use FormControl for forms:
selectBindType="control" [selectFormControl]="myControl"Handle empty selections:
[showEmptyOption]="true"Display multiple fields when helpful:
optionLabelFields="code,name,category"
Component Behavior
- Search: Type in the search box to filter options
- Filtering: Searches through fields specified in
filteredByFields - Selection: Click an option to select it
- Clear: Select empty option (if enabled) to clear selection
- Virtual Scroll: Renders only visible items for performance
This documentation covers all inputs, outputs, and usage patterns for the Search Select component.
