Reputation: 45
How is it possible to leave the autocomplete panel always enabled without having to focus on the input? I tried to activate the autofocus on the input, but it is not clean and the panel can always disappear when I press escape, for example. I also tried to call the openPanel() function, but it doesn't work in all cases, and it's still not the most optimized.
Upvotes: 0
Views: 158
Reputation: 45
In this case it is not recommended to use the Autocomplete material. I advise you to use a table instead, in which we can navigate with the arrows, click on a result, etc.
Create a table and a search input like this and set your column name and data
<input #searchbar
(keydown.arrowDown)="arrowDownEvent(row, selectedRowIndex)"
(keydown.arrowUp)="arrowUpEvent(row, selectedRowIndex)"
(keydown.enter)="submitSearch(searchbar.value)"
(focus)="selectedRowIndex=0" (focusout)="selectedRowIndex=undefined"
id="search-bar" placeholder="Search..."
required type="search">
<table mat-table [dataSource]="results" style="background-color: rgba(32, 32, 32); width: 100%">
<ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef> Name </th>
<td mat-cell *matCellDef="let result"><span>{{result.name}}<span></td>
</ng-container>
<!--You can add as many ng-containers as there are columns in your autocompletion results -->
<tr mat-header-row *matHeaderRowDef="displayedColumns; sticky: true"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns"
id="result.{{row.index}}"
[ngClass]="{'result': true, 'highlight': selectedRowIndex == row.index}"
(click)="submitSearch(row.name)">
</tr>
</table>
Then add this in your typescript so you can control the table
displayedColumns: string[] = ['name'];
selectedRowIndex: any = 0;
highlight(row: any){
(<HTMLInputElement>document.getElementById("search-bar")).value = row.name;
this.selectedRowIndex = row.index;
(<HTMLInputElement>document.getElementById("result."+this.selectedRowIndex)).scrollIntoView({block: 'end'});
}
arrowUpEvent(row: object, index: number){
if (index > 0) {
let nextRow = this.results[index - 1];
this.highlight(nextRow);
}
else {
let nextRow = this.results[this.results.length - 1];
this.highlight(nextRow)
}
}
arrowDownEvent(row: object, index: number){
if (index < this.results.length - 1) {
let nextRow = this.results[index + 1];
this.highlight(nextRow);
}
else {
let nextRow = this.results[0];
this.highlight(nextRow)
}
}
And finally you can add this to your css to modify the style of the selected element
.result {
background-color: rgba(32, 32, 32);
cursor: pointer;
}
.result.highlight {
background: rgb(25, 25, 25);
}
.result:hover {
background: rgb(42, 42, 42);
}
Your data should contain a column named index in order to be able to identify the results in the typescript.
Finally, you will have to create a submitSearch function with the user's search terms as an argument, which will define the actions carried out once the search has been carried out.
Here is an overview of what you can do with this method.
Upvotes: 2