Open matAutocomplete with open openPanel() method

altgov3en picture altgov3en · May 23, 2018 · Viewed 23.9k times · Source

I'm working with Angular Material's matAutocomplete component, and according to the docs, there is a method which can open/close an autocomplete panel with a openPanel()/closePanel() method. Any suggestion to how can I integrate it into already working example?

Here is a what I did with live example while trying to implement the feature.

Answer

Jai picture Jai · Jul 19, 2019

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.