3

I have an input instructorControl = new FormControl(); with an autocomplete. The autocompelte subscribes to this.instructorControl.valueChanges. When a suggestion from the autocomplete is selected or the add button is clicked, the current input value is pushed to an array and the input cleared with this.instructorControl.patchValue('');.

When an autocomplete option is selected, the autocomplete options menu is not opened again. For that, you either have to type something in or refocus the input.

How can I make the autocomplete reopen, when a suggestion is selected?

See this stackblitz. (Updated Sep 18)

app.component.html

  <button md-button (click)="addInstructor()">add</button>
  <md-input-container fxFlex>
    <input mdInput name="instructor" placeholder="instructor" (keydown.enter)="addInstructor()" [mdAutocomplete]="instructorsAuto" [formControl]="instructorControl">
  </md-input-container>


  <md-autocomplete #instructorsAuto="mdAutocomplete">
    <md-option *ngFor="let instructor of filteredInstructors | async" [value]="instructor" (click)="addInstructor()">
      {{ instructor }}
    </md-option>
  </md-autocomplete>

  {{instructors | json}}

app.component.ts

  instructors: string[] = [];
  instructorControl = new FormControl();
  filteredInstructors: Observable<string[]>;
  allInstructors = ['Max', 'Tirrell'];;
  instructorsAuto;

  ngOnInit() {
    this.filteredInstructors = this.instructorControl.valueChanges
      .startWith('')
      .map(value => this.filterInstructors(value));
  }

  addInstructor() {
    const instructor: string = this.instructorControl.value;
    if (instructor) {
      this.instructors.push(instructor);
      this.instructorControl.patchValue('');
    }
  }

  private filterInstructors(value: string = ''): string[] {
    return this.allInstructors.filter(instructor => new RegExp(`${value}`, 'gi').test(instructor));
Kim Kern
  • 54,283
  • 17
  • 197
  • 195
  • I updated the plunker from yurzui's answer in this stackblitz: https://stackblitz.com/edit/angular-x6hftl-fuxf8s?file=app/autocomplete-overview-example.ts – Kim Kern Sep 12 '18 at 18:12

1 Answers1

9

My suggestion is using @ViewChild decorator to get hold of MdAutocompleteTrigger instance and then fire openPanel() method on it.

In order to do this:

1) Add template reference variable to input[autocomplete] element:

<input #trigger ...
       [mdAutocomplete]="instructorsAuto"
       [formControl]="instructorControl">

2) Declare decorated by @ViewChild property.

import { MdAutocompleteTrigger } from '@angular/material'
...
@ViewChild('trigger', { read: MdAutocompleteTrigger }) trigger: MdAutocompleteTrigger;
                        ^^^^^^^^^^^^^^^^^^^^^^^^^
         make sure you're getting the right instance from template reference

3) Use it in your addInstructor method:

this.trigger.openPanel();

Stackblitz Example (Updated Sep 2018)

Kim Kern
  • 54,283
  • 17
  • 197
  • 195
yurzui
  • 205,937
  • 32
  • 433
  • 399
  • Explanation of the `read` property from Günter Zöchbauer [here](https://stackoverflow.com/a/37476195/968003). Basically, we strongly type an element, which otherwise would have appeared as `ElementRef ` – Alex Klaus Oct 05 '17 at 07:17
  • 1
    @AlexKlaus Explanation of the read property from yurzui https://stackoverflow.com/questions/39908967/how-to-get-reference-of-the-component-associated-with-elementref-in-angular-2/39909203#39909203 – yurzui Oct 05 '17 at 07:20
  • Thank you @yurzui! BTW, do you know how to pass a reference to the `trigger` element to a function from the HTML and still be able to call `MdAutocompleteTrigger`'s method? E.g. for ` Panic! ` and `function validate(auto: MdAutocompleteTrigger) { /* auto is just ElementRef here! */ }` – Alex Klaus Oct 05 '17 at 07:29
  • @AlexKlaus `triggerEl` is `HTMLInputElement` while `trigger` is directive instance https://plnkr.co/edit/KlHOLhrqfw9XLWNd89y9?p=preview – yurzui Oct 05 '17 at 07:41
  • 2
    hey @yurzui your sample is broken now, I couldn't figure out how can you open the trigger manually, for me it seems that it needs a small delay due the fact that when clicking in a element listed on it, when it hits the open line, it is still open so do nothing and then it close it as normal behaviour. Putting a setTimeout looks dirty I wonder if there is a better way. Thanks! – Alejandro Lora Apr 16 '18 at 08:06
  • @AlejandroLora Updated example https://plnkr.co/edit/h52cDvfZF1XOHtEdztWe?p=preview – yurzui Apr 16 '18 at 09:26
  • @yurzui What about triggering `optionSelected` event programmaticallay using `@ViewChild` etc? – Jack Dec 12 '20 at 11:34