Spartans get ready! v1 is coming!
We are very close to our first stable release. Expect more announcements in the coming weeks. v1 was made possible by our partner Zerops.
- Accordion
- Alert
- Alert Dialog
- Aspect Ratio
- Autocomplete
- Avatar
- Badge
- Breadcrumb
- Button
- Button Group
- Calendar
- Card
- Carousel
- Checkbox
- Collapsible
- Combobox
- Command
- Context Menu
- Data Table
- Date Picker
- Dialog
- Dropdown Menu
- Empty
- Form Field
- Hover Card
- Icon
- Input Group
- Input OTP
- Input
- Item
- Kbd
- Label
- Menubar
- Pagination
- Popover
- Progress
- Radio Group
- Resizable
- Scroll Area
- Select
- Separator
- Sheet
- Sidebar
- Skeleton
- Slider
- Sonner (Toast)
- Spinner
- Switch
- Table
- Tabs
- Textarea
- Toggle
- Toggle Group
- Tooltip
Autocomplete
Autocomplete input and dropdown selection with filtering options.
import { Component, computed, signal } from '@angular/core';
import { HlmAutocomplete } from '@spartan-ng/helm/autocomplete';
@Component({
selector: 'spartan-autocomplete-preview',
imports: [HlmAutocomplete],
template: `
<hlm-autocomplete [filteredOptions]="filteredOptions()" [(search)]="search" />
`,
})
export class AutocompletePreview {
private readonly _options: string[] = [
'Marty McFly',
'Doc Brown',
'Biff Tannen',
'George McFly',
'Jennifer Parker',
'Emmett Brown',
'Einstein',
'Clara Clayton',
'Needles',
'Goldie Wilson',
'Marvin Berry',
'Lorraine Baines',
'Strickland',
];
public readonly search = signal('');
public readonly filteredOptions = computed(() =>
this._options.filter((option) => option.toLowerCase().includes(this.search().toLowerCase())),
);
}Installation
The Autocomplete component is built with the Popover component.
npx nx g @spartan-ng/cli:ui autocomplete
ng g @spartan-ng/cli:ui autocomplete
Usage
import { HlmAutocompleteImports } from '@spartan-ng/helm/autocomplete';<hlm-autocomplete [options]="options" />Examples
Custom Config
Use provideHlmAutocompleteConfig to define custom configurations for the autocomplete component. This is especially useful when the autocomplete's filteredOptions contain objects rather than plain strings.
transformOptionToString: (option: T) => string;defines how an option should be transformed into the string displayed in the dropdown list.transformValueToSearch: (option: T) => string;defines how the selected option should be transformed into the string written to the search input.
You can customize a specific instance of hlm-autocomplete by passing transformOptionToString and transformValueToSearch directly as inputs. This allows you to modify the behavior for just that instance, without affecting all autocompletes configured via provideHlmAutocompleteConfig .
import { Component, computed, signal } from '@angular/core';
import { HlmAutocompleteImports } from '@spartan-ng/helm/autocomplete';
import { provideHlmAutocompleteConfig } from 'libs/helm/autocomplete/src/lib/hlm-autocomplete.token';
type Country = {
name: string;
code: string;
flag: string;
};
@Component({
selector: 'spartan-autocomplete-config',
imports: [HlmAutocompleteImports],
template: `
<hlm-autocomplete [filteredOptions]="filteredCountries()" [(search)]="search" />
`,
providers: [
provideHlmAutocompleteConfig({
transformOptionToString: (option: Country) => `${option.flag} ${option.name}`,
transformValueToSearch: (option: Country) => `${option.flag} ${option.name}`,
}),
],
})
export class AutocompleteConfig {
private readonly _countries: Country[] = [
{ name: 'Argentina', code: 'AR', flag: '🇦🇷' },
{ name: 'Australia', code: 'AU', flag: '🇦🇺' },
{ name: 'Belgium', code: 'BE', flag: '🇧🇪' },
{ name: 'Brazil', code: 'BR', flag: '🇧🇷' },
{ name: 'Canada', code: 'CA', flag: '🇨🇦' },
{ name: 'China', code: 'CN', flag: '🇨🇳' },
{ name: 'France', code: 'FR', flag: '🇫🇷' },
{ name: 'Germany', code: 'DE', flag: '🇩🇪' },
{ name: 'India', code: 'IN', flag: '🇮🇳' },
{ name: 'Italy', code: 'IT', flag: '🇮🇹' },
{ name: 'Japan', code: 'JP', flag: '🇯🇵' },
{ name: 'Mexico', code: 'MX', flag: '🇲🇽' },
{ name: 'Netherlands', code: 'NL', flag: '🇳🇱' },
{ name: 'Norway', code: 'NO', flag: '🇳🇴' },
{ name: 'Russia', code: 'RU', flag: '🇷🇺' },
{ name: 'South Africa', code: 'ZA', flag: '🇿🇦' },
{ name: 'South Korea', code: 'KR', flag: '🇰🇷' },
{ name: 'Spain', code: 'ES', flag: '🇪🇸' },
{ name: 'Sweden', code: 'SE', flag: '🇸🇪' },
{ name: 'Switzerland', code: 'CH', flag: '🇨🇭' },
{ name: 'United Kingdom', code: 'GB', flag: '🇬🇧' },
{ name: 'United States', code: 'US', flag: '🇺🇸' },
];
public readonly search = signal<string>('');
public readonly filteredCountries = computed(() =>
this._countries.filter(
(country) =>
country.name.toLowerCase().includes(this.search().toLowerCase()) ||
`${country.flag} ${country.name}`.toLowerCase().includes(this.search().toLowerCase()),
),
);
}Custom Option Template
You can customize the rendering of each option in the dropdown list by using the ng-template with the optionTemplate input. This is especially useful when filteredOptions are objects instead of simple strings, or when you want to display additional content such as icons, descriptions, or custom formatting alongside the option text.
import { Component, computed, signal } from '@angular/core';
import { HlmAutocompleteImports } from '@spartan-ng/helm/autocomplete';
import { provideHlmAutocompleteConfig } from 'libs/helm/autocomplete/src/lib/hlm-autocomplete.token';
type Country = {
name: string;
code: string;
flag: string;
};
@Component({
selector: 'spartan-autocomplete-countries',
imports: [HlmAutocompleteImports],
template: `
<hlm-autocomplete [filteredOptions]="filteredCountries()" [optionTemplate]="option" [(search)]="search" />
<!-- custom option template with access to the option item -->
<ng-template #option let-option>{{ option.flag }} {{ option.name }}</ng-template>
`,
providers: [
provideHlmAutocompleteConfig({
transformValueToSearch: (option: Country) => `${option.flag} ${option.name}`,
}),
],
})
export class AutocompleteCountries {
private readonly _countries: Country[] = [
{ name: 'Argentina', code: 'AR', flag: '🇦🇷' },
{ name: 'Australia', code: 'AU', flag: '🇦🇺' },
{ name: 'Belgium', code: 'BE', flag: '🇧🇪' },
{ name: 'Brazil', code: 'BR', flag: '🇧🇷' },
{ name: 'Canada', code: 'CA', flag: '🇨🇦' },
{ name: 'China', code: 'CN', flag: '🇨🇳' },
{ name: 'France', code: 'FR', flag: '🇫🇷' },
{ name: 'Germany', code: 'DE', flag: '🇩🇪' },
{ name: 'India', code: 'IN', flag: '🇮🇳' },
{ name: 'Italy', code: 'IT', flag: '🇮🇹' },
{ name: 'Japan', code: 'JP', flag: '🇯🇵' },
{ name: 'Mexico', code: 'MX', flag: '🇲🇽' },
{ name: 'Netherlands', code: 'NL', flag: '🇳🇱' },
{ name: 'Norway', code: 'NO', flag: '🇳🇴' },
{ name: 'Russia', code: 'RU', flag: '🇷🇺' },
{ name: 'South Africa', code: 'ZA', flag: '🇿🇦' },
{ name: 'South Korea', code: 'KR', flag: '🇰🇷' },
{ name: 'Spain', code: 'ES', flag: '🇪🇸' },
{ name: 'Sweden', code: 'SE', flag: '🇸🇪' },
{ name: 'Switzerland', code: 'CH', flag: '🇨🇭' },
{ name: 'United Kingdom', code: 'GB', flag: '🇬🇧' },
{ name: 'United States', code: 'US', flag: '🇺🇸' },
];
public readonly search = signal<string>('');
public readonly filteredCountries = computed(() =>
this._countries.filter(
(country) =>
country.name.toLowerCase().includes(this.search().toLowerCase()) ||
`${country.flag} ${country.name}`.toLowerCase().includes(this.search().toLowerCase()),
),
);
}Asynchronous
import { Component, resource, signal } from '@angular/core';
import { HlmAutocompleteImports } from '@spartan-ng/helm/autocomplete';
import { HlmSpinnerImports } from '@spartan-ng/helm/spinner';
@Component({
selector: 'spartan-autocomplete-async',
imports: [HlmAutocompleteImports, HlmSpinnerImports],
template: `
<hlm-autocomplete [filteredOptions]="options.value()" [loading]="options.isLoading()" [(search)]="search">
<hlm-spinner loading class="size-6" />
</hlm-autocomplete>
`,
})
export class AutocompleteAsync {
public readonly search = signal('');
public options = resource({
defaultValue: [],
request: () => ({ search: this.search() }),
loader: async (params) => {
const search = params.request.search;
if (search.length === 0) {
return [];
}
// Simulate empty state
if (search === 'empty') {
return [];
}
// DEV - call your API or 3rd party service here
// simulate async
return new Promise<string[]>((resolve) => {
setTimeout(() => {
const newOptions = Array.from({ length: 15 }, (_, i) => `${search}-${i + 1}`);
resolve(newOptions);
}, 500);
});
},
});
}Form
import { Component, computed, inject, signal } from '@angular/core';
import { FormBuilder, ReactiveFormsModule, Validators } from '@angular/forms';
import { HlmAutocompleteImports } from '@spartan-ng/helm/autocomplete';
import { HlmButtonImports } from '@spartan-ng/helm/button';
import { HlmLabelImports } from '@spartan-ng/helm/label';
@Component({
selector: 'spartan-autocomplete-form',
imports: [HlmAutocompleteImports, ReactiveFormsModule, HlmButtonImports, HlmLabelImports],
template: `
<form [formGroup]="form" (ngSubmit)="submit()" class="space-y-8">
<div class="flex flex-col gap-2">
<label for="autocomplete" hlmLabel class="px-1">Choose your favorite character</label>
<hlm-autocomplete
inputId="autocomplete"
[filteredOptions]="filteredOptions()"
[(search)]="search"
formControlName="option"
/>
</div>
<button type="submit" hlmBtn>Submit</button>
</form>
`,
})
export class AutocompleteForm {
private readonly _formBuilder = inject(FormBuilder);
private readonly _options: string[] = [
'Marty McFly',
'Doc Brown',
'Biff Tannen',
'George McFly',
'Jennifer Parker',
'Emmett Brown',
'Einstein',
'Clara Clayton',
'Needles',
'Goldie Wilson',
'Marvin Berry',
'Lorraine Baines',
'Strickland',
];
public readonly search = signal('');
public form = this._formBuilder.group({
option: [null, Validators.required],
});
public readonly filteredOptions = computed(() =>
this._options.filter((option) => option.toLowerCase().includes(this.search().toLowerCase())),
);
submit() {
console.log(this.form.value);
}
}Brain API
BrnAutocompleteEmpty
Selector: [brnAutocompleteEmpty]
BrnAutocompleteGroup
Selector: [brnAutocompleteGroup]
Inputs
| Prop | Type | Default | Description |
|---|---|---|---|
| id | string | `brn-autocomplete-group-${++BrnAutocompleteGroup._id}` | The id of the autocomplete list |
BrnAutocompleteItem
Selector: button[brnAutocompleteItem]
Inputs
| Prop | Type | Default | Description |
|---|---|---|---|
| id | unknown | `brn-autocomplete-item-${++BrnAutocompleteItem._id}` | A unique id for the item |
| value* (required) | T | - | The value this item represents. |
| disabled | boolean | false | Whether the item is disabled. |
Outputs
| Prop | Type | Default | Description |
|---|---|---|---|
| selected | void | - | Emits when the item is selected. |
BrnAutocompleteList
Selector: [brnAutocompleteList]
Inputs
| Prop | Type | Default | Description |
|---|---|---|---|
| id | string | `brn-autocomplete-list-${++BrnAutocompleteList._id}` | The id of the command list |
BrnAutocompleteSearchInput
Selector: input[brnAutocompleteSearchInput]
Inputs
| Prop | Type | Default | Description |
|---|---|---|---|
| value | string | - | The initial value of the search input |
Outputs
| Prop | Type | Default | Description |
|---|---|---|---|
| valueChange | string | - | Emitted when the value changes |
| valueChanged | string | - | The initial value of the search input |
BrnAutocomplete
Selector: [brnAutocomplete]
Inputs
| Prop | Type | Default | Description |
|---|---|---|---|
| id | string | `brn-autocomplete-${++BrnAutocomplete._id}` | The id of the autocomplete |
Outputs
| Prop | Type | Default | Description |
|---|---|---|---|
| valueChange | T | - | when the selection has changed |
Helm API
HlmAutocompleteEmpty
Selector: [hlmAutocompleteEmpty]
Inputs
| Prop | Type | Default | Description |
|---|---|---|---|
| class | ClassValue | - | - |
HlmAutocompleteGroup
Selector: hlm-autocomplete-group
Inputs
| Prop | Type | Default | Description |
|---|---|---|---|
| class | string | - | The user defined class |
HlmAutocompleteItem
Selector: button[hlm-autocomplete-item]
Inputs
| Prop | Type | Default | Description |
|---|---|---|---|
| class | string | - | The user defined class |
HlmAutocompleteList
Selector: hlm-autocomplete-list
Inputs
| Prop | Type | Default | Description |
|---|---|---|---|
| class | string | - | The user defined class |
HlmAutocompleteSearchInput
Selector: input[hlm-autocomplete-search-input]
Inputs
| Prop | Type | Default | Description |
|---|---|---|---|
| class | ClassValue | - | The user defined class |
HlmAutocompleteSearch
Selector: hlm-autocomplete-search
Inputs
| Prop | Type | Default | Description |
|---|---|---|---|
| class | ClassValue | - | The user defined class |
HlmAutocompleteTrigger
Selector: [hlmAutocompleteTrigger]
Inputs
| Prop | Type | Default | Description |
|---|---|---|---|
| disabledTrigger | boolean | false | Whether the trigger is disabled. |
HlmAutocomplete
Selector: hlm-autocomplete
Inputs
| Prop | Type | Default | Description |
|---|---|---|---|
| class | ClassValue | - | The user defined class |
| autocompleteSearchClass | ClassValue | - | Custom class for the autocomplete search container. |
| autocompleteInputClass | ClassValue | - | Custom class for the autocomplete input. |
| autocompleteListClass | ClassValue | - | Custom class for the autocomplete list. |
| autocompleteItemClass | ClassValue | - | Custom class for each autocomplete item. |
| autocompleteEmptyClass | ClassValue | - | Custom class for the empty and loading state container. |
| filteredOptions | T[] | [] | The list of filtered options to display in the autocomplete. |
| value | T | - | The selected value. |
| search | string | - | The search query. |
| transformValueToSearch | (option: T) => string | this._config.transformValueToSearch | Function to transform an option value to a search string. Defaults to identity function for strings. |
| transformOptionToString | (option: T) => string | this._config.transformOptionToString | Function to transform an option value to a display string. Defaults to identity function for strings. |
| optionTemplate | TemplateRef<HlmAutocompleteOption<T>> | - | Optional template for rendering each option. |
| loading | boolean | false | Whether the autocomplete is in a loading state. |
| searchPlaceholderText | unknown | Select an option | Placeholder text for the input field. |
| loadingText | unknown | Loading options... | Text to display when loading options. |
| emptyText | unknown | No options found | Text to display when no options are found. |
| ariaLabelToggleButton | string | Toggle options | Aria label for the toggle button. |
| inputId | string | `hlm-autocomplete-input-${++HlmAutocomplete._id}` | The id of the input field. |
| disabled | boolean | false | Whether the autocomplete is disabled. |
Outputs
| Prop | Type | Default | Description |
|---|---|---|---|
| valueChange | T | null | - | Emitted when the selected value changes. |
| searchChange | string | - | Emitted when the search query changes. |
On this page