34

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.

altgov3en
  • 1,100
  • 2
  • 18
  • 33

3 Answers3

41

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.

Community
  • 1
  • 1
Jai
  • 2,768
  • 24
  • 20
  • 1
    this works fine with single panel but when you have two panels in page, `$event.stopPropagation()` causes any previous panels to remain open. any ideas how to fix it? – aycanadal Apr 12 '20 at 14:18
  • I used this slightly differently, but +1'd for `#trigger="matAutocompleteTrigger"`, I could not for the life of me figure out how the trigger was exposed so I could programmatically call `.openPanel()`. Thank you! – mhodges Nov 20 '20 at 18:15
  • 3
    This is all great, but it doesn't work in conjunction with the `(optionSelected)` Output of ``. – Russ Jul 12 '21 at 18:17
  • Can you please help me to understand what the `matAutocompleteTrigger` with lowercase `m` means? –  Jul 16 '21 at 10:10
  • @QianChen That's the exported name of MatAutocompleteTrigger as described in https://material.angular.io/components/autocomplete/api#MatAutocompleteTrigger – Florian Bachmann Jul 19 '21 at 15:59
30

in template

<button (click)='openPanel($event)'>Open</button>

<input #inputAutoComplete>

in ts

@ViewChild(MatAutocompleteTrigger, {read: MatAutocompleteTrigger}) inputAutoComplete: MatAutocompleteTrigger;


openPanel(evt): void {
  evt.stopPropagation();
  this.inputAutoComplete.openPanel();
}
Pankaj Parkar
  • 134,766
  • 23
  • 234
  • 299
10

Please add stopPropagation or defer the openPanel using setTimeout as follows.

Because at button click end focus changes from input field back to ur button so autocomplete is hiding immediately

Option 1: Stop Propagatioan

<button (click)="openAutocomplete($event)">toggle autocomplete (1 way)</button>
...
openAutocomplete(evt) {
  evt.stopPropagation()
  this.autoTrigger.openPanel();
}

Option 2 - SetTimeout

openAutocomplete() {
  setTimeout(() => {
    this.autoTrigger.openPanel();
  }, 0)
}
Abinesh Devadas
  • 1,517
  • 13
  • 15
  • 5
    your just missing the definition for this.autoTrigger should be like this: @ViewChild('input', { static: true }) autoTrigger: MatAutocompleteTrigger; html: – amit Jul 03 '19 at 12:24