7

I have a mat-autocomplete component with the options wired up to be populated from a service call as the user types (partial search):

<mat-autocomplete #auto="matAutocomplete" (optionSelected)="areaSelected($event.option.value)">
      <mat-option *ngFor="let option of options" [value]="option">{{ option }}</mat-option>
</mat-autocomplete>

In my TS code, I am setting the options array to be an empty array at the end of the processing I do when a user selects a value:

  resetFetchedOptions() {
    this.options = [];
}

This works in that the code is called, and that this.options is set to an empty array. The problem is that when the user tries to type another value in the field, the previous options are still there. If they type, the options get cleared out, and the new options based on the partial search are populated, so I think this is a rendering problem, but I'm a bit new to Angular Material, so I'm not sure if this is the wrong approach or I'm missing a step.

Thanks!

James Bender
  • 1,175
  • 1
  • 11
  • 22

2 Answers2

4

Are you using reactive forms? I made a similar thing like this (based on this article);

html

<mat-form-field class="width-filler">
    <input type="text" matInput placeholder="Search" [matAutocomplete]="auto" [formControl]="formControl" autocomplete="off" autofocus>
    <mat-autocomplete #auto="matAutocomplete" [displayWith]="displayFunc">
        <mat-option *ngIf="isSearching" class="is-loading"><mat-spinner diameter="20"></mat-spinner></mat-option>
        <mat-option *ngFor="let result of filteredResult" [value]="result">
            {{result.description}}
        </mat-option>
    </mat-autocomplete>
    <mat-hint>{{searchHint()}}</mat-hint>
</mat-form-field>

Typescript

ngOnInit() {
    this.formControl
        .valueChanges
        .pipe(
            debounceTime(300),
            tap(() => this.isSearching = true),
            switchMap(value => this.someService.searchStuff<ResultType[]>(this.getSearchString(value as any))
                .pipe(
                    finalize(() => this.isSearching = false),
                )
            )
        )
        .subscribe(result => this.filteredResult = result);

    this.formControl.valueChanges.subscribe(value => this.setValue(value));
}

// Need to handle both the search string and a selected full type
private setValue(value: string | ResultType) : void {
    if (typeof value === "string")
        this.selectedValue = null;
    else
        this.selectedValue = value;
}

private getSearchString(value: string | ResultType) {
    if (typeof value === "string")
        return value;
    else
        return value.description;
}
DaggeJ
  • 2,094
  • 1
  • 10
  • 22
  • I combined part of your answer with Javier's answer above and an idea I had and it works! Thanks! – James Bender Sep 04 '19 at 11:28
  • Glad it helped. Please consider upvoting / marking as answer if applicable :) – DaggeJ Sep 04 '19 at 11:32
  • Upvoted. Would mark as answer, but it was really a 50/50 job with Javier, so I'm not sure that's fair to him. Wish I could mark you both, sorry. ☹️ – James Bender Sep 05 '19 at 09:59
  • I would voted down if I have enough reputation. I am sorry to make such a huge staff just claer option list. – Jack Dec 12 '20 at 12:09
1

I think it happens because you keep a reference to the original array, try this.options.length=0 instead of = []

Javier Aviles
  • 7,952
  • 2
  • 22
  • 28
  • 1
    Tried this, got the same result. But, I combined it DaggeJ's answer and some tweaking of my own and came up with a fix. Thanks! – James Bender Sep 04 '19 at 11:27