Coding exercise: build an autocomplete dropdown in Angular.
Model answer
Combine a form control, debounced valueChanges, a list of matches and keyboard control. Angular Material has an autocomplete, but be ready to build a simple one.
@Component({
selector: 'app-autocomplete',
imports: [ReactiveFormsModule],
template: `
<input role="combobox" [attr.aria-expanded]="matches().length > 0" [formControl]="q"
(keydown.arrowdown)="move(1, $event)" (keydown.arrowup)="move(-1, $event)" (keydown.enter)="choose(matches()[active()])" />
@if (matches().length) {
<ul role="listbox">
@for (m of matches(); track m; let i = $index) {
<li role="option" [attr.aria-selected]="i === active()" (mousedown)="choose(m)">{{ m }}</li>
}
</ul>
}`,
})
export class Autocomplete {
options = input.required<string[]>();
picked = output<string>();
q = new FormControl('', { nonNullable: true });
active = signal(0);
private term = toSignal(this.q.valueChanges.pipe(debounceTime(200)), { initialValue: '' });
matches = computed(() => {
const t = this.term().toLowerCase();
return t ? this.options().filter((o) => o.toLowerCase().includes(t)).slice(0, 6) : [];
});
move(d: number, e: Event) { e.preventDefault(); this.active.update((a) => Math.max(0, Math.min(a + d, this.matches().length - 1))); }
choose(v?: string) { if (v) { this.q.setValue(v, { emitEvent: false }); this.picked.emit(v); this.active.set(0); } }
}For remote data, replace the computed with a switchMap to the API so older requests are cancelled.
Tips
- mousedown fires before the input loses focus, so the click is not lost.
Practise it yourself in the React and Angular code playground.
Learn this topic
Angular Tutorial: Beginner to Advanced .
Sign in to add your own answer.
More questions
- Coding exercise: build a Todo application in Angular.
- Coding exercise: create a search box with debounce in Angular.
- Coding exercise: fetch API data and display it in a table in Angular.
- Coding exercise: implement pagination in Angular.
- Coding exercise: create a login form with validation in Angular.
- Coding exercise: build a parent-child communication example in Angular.