The Material documentation should be clearer. Whilst there are various gymnastic routines you can do to achieve this functionality (like manipulating the document object, using @ViewChild, or creating event listeners), for me it boils down to the two following ways:
1 Minimalist:
<mat-form-field>
<input #nameInput
matInput
formControlName="name"
#trigger="matAutocompleteTrigger"
[matAutocomplete]="autoName">
<mat-autocomplete #autoName="matAutocomplete">
<mat-option *ngFor="let o of suggestionOpts"
[value]="o"
(click)="$event.stopPropagation(); trigger.openPanel()">{{o}}</mat-option>
</mat-autocomplete>
</mat-form-field>
Here we’re attaching the MatAutoCompleteTrigger
directive to the input and assigning it to a variable named trigger
. This trigger directive is passed to the click method on each mat-option
, which fires every time an option is selected from the menu. The directive contains two pertinent methods. Here we call openPanel
. We call stopPropagation
on the $event
object to prevent the native methods doing anything unexpected.
2 Explicitist:
.html
<mat-form-field>
<input #nameInput
matInput
formControlName="name"
#trigger="matAutocompleteTrigger"
[matAutocomplete]="autoName">
<mat-autocomplete #autoName="matAutocomplete">
<mat-option *ngFor="let o of suggestionOpts"
[value]="o"
(click)="selectionMade($event, trigger)">{{o}}</mat-option>
</mat-autocomplete>
</mat-form-field>
.ts
import { MatAutocompleteTrigger } from '@angular/material/autocomplete';
...
selectionMade(event: Event, trigger: MatAutocompleteTrigger) {
event.stopPropagation();
trigger.openPanel();
}
Here we’re passing the directive and event object to a function in the component’s .ts file, and performing exactly the same logic as the first approach. If blanket separation of concerns is a concern, do things this way. For small jobs like this I prefer the minimalist approach, but each unto their own, I guess.