Clear Angular Material autocomplete after selection

26,852

Solution 1

I think you're close, it looks like the only missing piece is resetting the form control value in selectCategory. This is how we accomplished it in our own app, but it's effectively the same thing:

/** Reference to the autocomplete trigger. */
@ViewChild(MdAutocompleteTrigger)
private trigger: MdAutocompleteTrigger;

/** Form control for the input. */
searchControl = new FormControl('');

ngAfterViewInit() {
  // Clear the input and emit when a selection is made
  this.trigger.autocomplete.optionSelected
    .map(event => event.option)
    .subscribe(option => {
      // This may or may not be needed, depending on your purposes
      option.deselect();

      // Emit the selection (so parent component can add chip)
      this.selection.emit(option.value);

      // Reset the value of the input
      this.searchControl.setValue('');
    });
}

Whenever you select a value, there will be a brief "flash" of the selected text. To avoid this, you can use the displayWith property to just display selected values as empty:

<md-autocomplete #auto="mdAutocomplete" [displayWith]="displayNull">
  ...
</md-autocomplete>

/** Display function for selected autocomplete values. */
displayNull(value) {
  return null;
}

Solution 2

Came across this solution, but I didn't like the displayNull fix.

My solution looks similar to this:

component.html:

  <input matInput [matAutocomplete]="auto" (input)="filter($event.target.value)" #autoInput>
  <mat-autocomplete #auto [displayWith]="displayKey" (optionSelected)="emit($event, autoInput)">
  // ...
  </mat-autocomplete>

component.ts:

@Output() optionSelected = new EventEmitter<MatAutocompleteSelectedEvent>();

emit(event: MatAutocompleteSelectedEvent, ele: HTMLInputElement) {
  ele.value = '';
  ele.blur();
  this.filter('');
  this.optionSelected.emit(event);
}

Solution 3

Here my approach

in template

...
<md-autocomplete #auto="mdAutocomplete" [displayWith]="displayNull" (optionSelected)="selectHandler($event)">
...

in component.ts

public selectHandler(event : MdAutocompleteSelectedEvent) : void
{
    event.option.deselect()
    this.doStuffWith(event.option.value)
}

public displayNull()
{
    return null
}

Solution 4

If you are using reactive forms the easiest way is to get the control and set the value to an empty string

In my case i had to do:

<input [matAutocomplete]="auto" formControlName="currentContact" type="text" matInput placeholder="Locatie">

this.reactiveForm = this.formBuilder.group({currentContact: ['']})
this.reactiveForm.get('currentContact').setValue('');
Share:
26,852
tobi
Author by

tobi

Updated on July 09, 2022

Comments

  • tobi
    tobi almost 2 years

    The problem I'm having is the following: the behaviour I need is, when an option is selected from the autocomplete input, it should add a chip to the Angular Material Chips component (which it does) and it should also clear the autocomplete input, so I can then select another option.

    This is my html:

    <div class="col-md-6">
       <md-form-field>
          <input type="text" placeholder="Categoría" aria-label="Categoría" mdInput [mdAutocomplete]="auto" [formControl]="categoryCtrl">
          <md-autocomplete #auto="mdAutocomplete" (optionSelected)="selectCategory($event)">
             <md-option *ngFor="let category of filteredCategories | async" [value]="category.name">
                {{ category.name }}
             </md-option>
          </md-autocomplete>
       </md-form-field>
    </div>
    

    This is my TypeScript code:

    constructor(private placeService: PlaceService, private categoryService: CategoryService) {
        this.categoryCtrl = new FormControl();
        this.filteredCategories = this.categoryCtrl.valueChanges
            .startWith('')
            .map(category => category ? this.filterCategories(category) : this.categories.slice());
    }
    
    filterCategories(name: string) {
        return this.categories.filter(category => category.name.toLowerCase().indexOf(name.toLowerCase()) === 0);
    }
    
    selectCategory(category: any) {
        const index = this.selectedCategories.indexOf(category.option.value);
        if (index === -1) {
            this.selectedCategories.push(category.option.value)
        }
    }
    

    I've checked the Angular Material documentation and I haven't found a method to do this.

    Thanks.

  • SkarXa
    SkarXa over 4 years
    I'm not using ReactiveForm, so this is great for me
  • Admin
    Admin over 3 years
    What about clearing input if there is not selected value? In this case I try to use input's blur() event, but in that case I cannot access the autocomplete value (if selected or not). Any idea?
  • Ted Elliott
    Ted Elliott over 2 years
    This seems to be the only solution that works with angular material >=12. setValue on the formControl works fine when not attached to an autocomplete.