Narendra Pandey
Narendra Pandey

Reputation: 436

How to clear mat- autocomplete when no option is selected from autocomplete dropdown

I have successfully implemented mat-autocomplete and it is working fine if selected from auto complete drop down. I am facing issues when i have typed in some text and navigate to other fields without selecting below dropped in auto complete fields. It retains the value typed in autocomplete field.

I have used below approach to fix this issue -

  1. MatAutocompleteTrigger - Below code I have used in ts file -

      @ViewChild('autoCompleteInput', { static: false,read: MatAutocompleteTrigger })  trigger: MatAutocompleteTrigger;
    .
    .
    .
    this.trigger.panelClosingActions
      .subscribe(e => {
       if (!(e && e.source)) {
       this.accountForm.get('accountId').setValue="";
       this.account.accountId = null;
       }
    })
    

    First of all , i am unable to keep it in any angular life cycle hook. This trigger doesn't get initialized during angular lifecycle hooks, but later while it receives any values form mat-autocomplete.So it clears value as soon I type in text in field(keeping the below autocomplete list; which doesn't look good)

    2.Used observalble on filterOptions(Obserable on my autocomplete field) - I have used below code for i t -

     this.filteredOptions = this.accountForm.get('accountId').valueChanges.pipe(
      debounceTime(250),
      distinctUntilChanged(),
      filter(searchString => typeof searchString === 'string'),
      filter(searchString => searchString.length > 0),
      switchMap(searchString => {
        return this.accountService.autoCompleteBrokerSearch(searchString);
      })
    );
    this.filteredOptions.takeUntil(this.ngUnsubscribe).subscribe((lookups: accountEntityModel[]) => {
      if (lookups.length === 0) {
        this.account.accountId = null;
        this.accountForm.get('accountId').patchValue('');
      }
      if(lookups.find(value => value.id !== this.account.id)){
        this.account.accountId = null;
        this.accountForm.get('accountId').patchValue('');
      }
    });
    

with Template code -

<mat-form-field  appearance="standard" >
<mat-label>{{ 'account.enterAccount' | translate }}</mat-label>
<input
 matInput
 formControlName="accountId"
 class="search-select"
 [matAutocomplete] = "accountAutocomplete"
#autoCompleteInput="matAutocompleteTrigger">
<mat-autocomplete #accountAutocomplete = "matAutocomplete" [displayWith]="displayFn.bind(this)" >

    <mat-option [value]="accountOption" *ngFor="let accountOption of filteredOptions | async" (onSelectionChange)="onEnteredAccount(accountOption)" >{{
        accountOption.description
      }}</mat-option>

</mat-autocomplete>

</mat-form-field>

I only require to clear the field if we have not selected anything from auto complete, and it should clear field values from form too.

Upvotes: 3

Views: 14034

Answers (3)

Mitul&#225;t b&#225;ti
Mitul&#225;t b&#225;ti

Reputation: 2166

It has been recently introduced to Angular 17 that when you use requireSelection mat-autocomplete field, it only accepts values from the list, otherwise it will be cleared. Example code from the official angular site:

HTML:

<form class="example-form">
    <mat-form-field class="example-full-width">
    <mat-label>Number</mat-label>
    <input #input
           type="text"
           placeholder="Pick one"
           matInput
           [formControl]="myControl"
           [matAutocomplete]="auto"
           (input)="filter()"
           (focus)="filter()">
    <mat-autocomplete requireSelection #auto="matAutocomplete">
      @for (option of filteredOptions; track option) {
        <mat-option [value]="option">{{option}}</mat-option>
      }
    </mat-autocomplete>
  </mat-form-field>
</form>

Typescript:

export class AutocompleteRequireSelectionExample {
  @ViewChild('input') input: ElementRef<HTMLInputElement>;
  myControl = new FormControl('');
  options: string[] = ['One', 'Two', 'Three', 'Four', 'Five'];
  filteredOptions: string[];

  constructor() {
    this.filteredOptions = this.options.slice();
  }

  filter(): void {
    const filterValue = this.input.nativeElement.value.toLowerCase();
    this.filteredOptions = this.options.filter(o => o.toLowerCase().includes(filterValue));
  }
}

Upvotes: 0

sweetnandha cse
sweetnandha cse

Reputation: 961

Its working fine for me..

HTML:

     <mat-form-field appearance="outline">
          <input type="text" placeholder="start type.." #autoCompleteInput="matAutocompleteTrigger"
              matInput [matAutocomplete]="catAuto" [formControl]="selectedData" (keyup)="onChange($event)">
          <mat-autocomplete #catAuto="matAutocomplete" [displayWith]="displayFnForAutoComplete"
              (optionSelected)="onSelect($event.option.value)">
              <mat-option *ngFor="let option of filterList" [title]="option" [value]="option.id">
                  {{option.name}}
              </mat-option>
          </mat-autocomplete>                  
     </mat-form-field>

TS:

@ViewChild('autoCompleteInput', { static: false, read: MatAutocompleteTrigger }) trigger: MatAutocompleteTrigger;
selectedData = new FormControl();

 ngAfterViewInit() {
    this.trigger.panelClosingActions
      .subscribe(e => {
        this.selectedData.setValue(null);
      });
  }

Upvotes: 1

JuNe
JuNe

Reputation: 1997

You can remove the formControl-binding from your input and when you select an option you set that id to your form.

You are already calling such a function (onSelectionChange)="onEnteredAccount(accountOption)" in which you can do that.

Upvotes: 0

Related Questions