Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Autocomplete does not show after setValue

I'm building a form where I use the Angular Material Autocomplete module. I load the options from a server and I filter them with an input. It works great, and now I wanted to add a "clear" icon to clear the field if needed.

The clear option clears the field, but it doesn't show the autocomplete options again. It shows them when I manually delete the input contents with backspace but not with the icon.

To "clear" the field I use this code:

clear(control: string): void {
    this.form.get(control).setValue('');
}

And I call it from a mat-icon component:

<mat-form-field>
    <input matInput type="text" ... >
    <mat-icon matSuffix (click)="clear(fieldName)" ...>
        clear</mat-icon>
</mat-form-field>
<mat-autocomplete> ... </mat-autocomplete>

Where fieldName (string) is the name of the control I want to clear.

And this is how I filter the autocomplete options:

this.filter = this.form.get(field).valueChanges.pipe(
    startWith(''), // Don't even know what this does...
    map(value => this.options.filter(option => option.name.toLowerCase().includes(value.toString().toLowerCase())))
);

I suspect that maybe there's an error with the setValue('') inside the clear() method. Or maybe its the filter method that I'm using.

Here's the full example in StackBlitz:

https://stackblitz.com/edit/angular-autocomplete-clear9zzmw2

like image 838
JCAguilera Avatar asked Nov 07 '18 15:11

JCAguilera


1 Answers

It seems like you want to open the options panel as soon as you click on clear button. This is not happening because once you select an option of matAutocomplete, it selects the value and close the options panel. In order to open it again you have to either remove character from textbox or type matching character sequence.

Over here you are manually clearing up the value, but it doesn't intimate matAutoComplete to open the panel. If you look at source code of matAutocomplete you will find that input/blur/keydown event happened are responsible for opening and closing panel. You can do that by triggering those event manually(into separate change detection cycle). But the most convenient way would be calling openPanel method of matAutocomplete.

So lets concentrate on how can we do call openPanel method of matAutocomplete. Since you've used matAutocomplete with combination of matInput, it does exported as matAutocompleteTrigger. So add #automcomplete="matAutocompleteTrigger" inside your matInput element like shown below.

Markup

<input
  matInput
  type="text"
  #automcomplete="matAutocompleteTrigger"
  placeholder="Select something"
  formControlName="autocomplete"
  [matAutocomplete]="autocompleteStuff"
  required>

Now using ViewChild decorator we can query autocomplete template variable

Component

// It will have an autocomplete component instance
@ViewChild('automcomplete') autocomplete;
//...
//...
clear(control: string): void {
    this.form.get(control).setValue('');
    // call autoComplete `openPanel` to show up options
    setTimeout(()=> {this.autocomplete.openPanel() })
}

Running Demo


Alternative solution could be blur out and focus in to the input programmatically. For the same just keep #automcomplete on matInput and then query the element using ViewChild and then trigger event on the nativeElement of queried result.

Html

<input
  matInput
  type="text"
  #automcomplete
  placeholder="Select something"
  formControlName="autocomplete"
  [matAutocomplete]="autocompleteStuff"
  required>

Component

@ViewChild('automcomplete') autocomplete;
//...
//...
clear(control: string): void {
    this.form.get(control).setValue('');
    setTimeout(()=> {
      this.autocomplete.nativeElement.blur();
      this.autocomplete.nativeElement.focus();
    })
}

Forked Demo

like image 143
Pankaj Parkar Avatar answered Oct 23 '22 03:10

Pankaj Parkar