Angular Material: Hide Autocomplete Panel when User hits enter Key

28,388

Solution 1

My use case was slightly different so your update didn't work for me, but I found a slightly different solution that does the trick:

@ViewChild(MatAutocompleteTrigger) autocomplete: MatAutocompleteTrigger;

Then you can use this to close the dropdown options:

this.autocomplete.closePanel(); 

Make sure to also import ViewChild:

import { ViewChild } from '@angular/core';

Works like a charm.

Solution 2

This comment provides a solution where you can get a reference to the matAutocompleteTrigger directly on the input element, so that you can call closePanel() within the template. For example:

    <input
      type="text"
      matInput
      #trigger="matAutocompleteTrigger"
      (keydown.enter)="$event.target.blur(); trigger.closePanel()"
      [formControl]="myControl"
      [matAutocomplete]="auto"
    />

Solution 3

// This is my solution  ios/android panel not hide on done button virtual // 


<input type="text" placeholder="{{lbl.TipDoc}}"
class="form-control ui-inputtext ui-widget autocomp"
 #trigautoTipDoc ="matAutocompleteTrigger"
 aria-label="name" matInput                                        (blur)="OcuPanelAuto(trigautoTipDoc);"
formControlName="tipDocLbl" [matAutocomplete]="autoTipDoc" >
<mat-autocomplete #autoTipDoc="matAutocomplete" role="combobox">
<mat-option  *ngFor="let option of tipDocFiltObs | async"
                                                            [value]="option.name">
 {{option.name}}
</mat-option>
</mat-autocomplete>


OcuPanelAuto(cc: MatAutocompleteTrigger) {
        setTimeout(function a() {
            cc.closePanel();
        }, 130);
    }
Share:
28,388

Related videos on Youtube

Ekos
Author by

Ekos

Updated on May 14, 2020

Comments

  • Ekos
    Ekos almost 4 years

    I'm currently working on a table where the user is able to tab through editable elements by pressing enter. I also use Angular Material in this.

    I have a mat-form-field with several dynamically created input fields with the mat-autocomplete element. However my enter key event acts a bit different in this.

    When you press on the input field, a panel will open (dropdown) where the user can select the input or he can simply write himself and the panel will give suggestions (autocomplete).

    What happens if you press the tab key?

    If you press on tab while typing, the cursor will move onto the next editable element and the panel (dropdown) of the latest element will close.

    What happens if you press the enter key

    If you press on enter while typing, the cursor will move onto the next editable element HOWEVER the panel (dropdown) of the latest element stays open which resulst in multiple input fields having an open dropdown panel even though the user has already wrote what he needed to.

    Template:

    <tr *ngFor="let row of rows; let rowIdx = index">
                <td *ngFor="let col of columns; let colIdx = index">
                    <mat-form-field class="example-full-width">             
                    <input  #inputs type="text" placeholder="Pick one" aria-label="Number" matInput [formControl]="myControl" [matAutocomplete]="auto"
                        (keyup.enter)="shiftFocusEnter(rowIdx, colIdx)">
                        <mat-autocomplete #auto="matAutocomplete">
                                <mat-option *ngFor="let option of filteredOptions | async" [value]="option">
                                {{ option }}
                                </mat-option>
                            </mat-autocomplete>
                        </mat-form-field>
                </td>
          </tr>
    

    This simply creates rows based on the number of objects in an array (not quite important here).

    There's also a keyup.enter event on the input fields which gets triggered when ever the user presses on enter while focus is on an input field and passes row index and column index to get the next editable element.

    Component:

    shiftFocusEnter(rowIdx: number, colIdx: number) {
    console.log("Enter", rowIdx, colIdx);  
    if(colIdx == 4 && rowIdx == 5) {
      console.log("Reached end of row");
    }
    else {
      colIdx = colIdx + this.columns.findIndex(c => c.editable);
      this.autocomplete.showPanel = false;
      this.focusInput(rowIdx, colIdx);
    }
    

    }

    This function receives two parameters. Row Index and Column Index and calculates the index of the next editable element to focus on that.

    The line this.autocomplete.showPanel = false was written to see if I could simply close the panel like this but it didnt work.

    this.autocomplete is an object of class MatAutocomplete. I've added this by writing

    @Input('matAutocomplete')
    autocomplete: MatAutocomplete
    

    What I need:

    I want the dropdown panel of the mat autocomplete element to close after pressing enter.

    Thanks in advance!

    Update:

    So after working a bit I found this

    @ViewChild('test', { read: MatAutocompleteTrigger }) test: MatAutocompleteTrigger;
    

    +

    this.test.closePanel();
    

    This time I'm able to close the panel of the FIRST cell in the table however all the panels of the other input fields will stay open

    • Jota.Toledo
      Jota.Toledo over 6 years
      Instead of @Input, you should use @ViewChildren
  • Sean Duggan
    Sean Duggan over 4 years
    I was totally missing that it was the trigger that I needed to reference in the code. Thank you!
  • Joe
    Joe about 4 years
    If you patchValue or setValue on an input that uses material autocomplete, the panel will remain open afterwards. This solution is ideal to close that panel after updating the value. Thanks!!
  • Pierre
    Pierre over 3 years
    (blur)="trigger.closePanel()" works great! However if you have multiple auto complete controls, give every control a different trigger name ie. #triggerName="matAutocompleteTrigger", #triggerLastname="matAutocompleteTrigger" and then add (blur)="triggerName.closePanel()" and (blur)="triggerLastname.closePanel()" respectively.