Trying to create an Autocomplete component functionality.
When a user starts typing, a small window pops up with options to select from. I would like the user to be able to pick an option using his keyboard.
Example: - User typing "Hou" - Options show ["House", "Houston"] - User hits down keyboard key and hits enter to select "house"
My pop up scroll component:
<ul class="plDropdown-optionList">
<cdk-virtual-scroll-viewport style="height: 200px" itemSize="30">
<ng-container *cdkVirtualFor="let option of displayableOptions">
<button class="plDropdown-option" type="button" (click)="selectOption(option)">
{{option}}
</button>
</ng-container>
</cdk-virtual-scroll-viewport>
</ul>
Posting a solution option for anyone looking for this.
I used keyboard event from Input tag:
<input (keydown)="processInput($event)">
Then finding which was pressed:
processInput(evt: KeyboardEvent): void
Keeping selected reference, and updating it:
private _updateIndex(key: string): void {
switch (key) {
case Key.ArrowUp:
if (this.selectedIndex === 0) {
return;
}
this._setIndex(this.selectedIndex -= 1);
break;
case Key.ArrowDown:
this.displayedTags$
.pipe(
take(1)
)
.subscribe((results) => {
if (this.selectedIndex >= results.length - 1) {
this._setIndex(results.length - 1);
return;
}
this._setIndex(this.selectedIndex += 1);
});
break;
default:
break;
}
}
private _selectIndex(): void {
this.displayedTags$.pipe(
take(1)
)
.subscribe((results) => {
const result = results[this.selectedIndex];
if (result) {
this.selectResult(result);
}
});
}
private _setIndex(index: number): void {
this.selectedIndex = index;
}
At HTML file, use this line for highlight the currect line:
[ngClass]="{'focus-background': selectedIndex == idx}"
it looks like this:
<cdk-virtual-scroll-viewport style="height: 400px" itemSize="30">
<ng-container *cdkVirtualFor="let option of displayedTags$ | async; index as idx" (isSelected)="true">
<button class="plTagsComponent-option" type="button" (click)="selectResult(option)" (isSelected)="true"
[ngClass]="{'focus-background': selectedIndex == idx}" (mouseenter)="onHover(idx) ">
{{option.label}}
</button>
</ng-container>
</cdk-virtual-scroll-viewport>