Clear Angular Material autocomplete after selectio

2020-05-29 04:05发布

问题:

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.

回答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;
}


回答2:

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
}


回答3:

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);
}