angularangular-materialobservableangular5mat-autocomplete

Angular autocomplete with Observable


I am facing a problem with the autocomplete of Angular, I don't manage to display the names instead of the id as you can see on the here : enter image description here

I get my datas as Observable as you can see below :

autocomplete.component.ts:

driverListItem$: Observable<DriverListItem[]>;
ngOnInit() {
    this.driverListItem$ = this.driverListItemService.getList(+subcontractorId);
}

autocomplete.service.ts:

getList(subcontractorId?: number): Observable<DriverListItem[]> {
    return this.http.get<DriverListItem[]>(
      this.apiUrl,
      {
        params: new HttpParams().append('subcontractorId', subcontractorId.toString()),
        headers: this.getAuthHeaders(this.authService.token),
      }
    )
    .do(
      value => console.debug('DriverListItemService getList value', value),
      error => {
          console.debug('DriverListItemService getList error', error);
          this.handleError(error);
      },
    );
  }

autocomplete.component.html:

<mat-form-field style="width:100px">
  <input matInput name="assignedOperator" [(ngModel)]="entity.assignedOperator" [matAutocomplete]="auto" />
  <mat-autocomplete #auto="matAutocomplete">
    <mat-option *ngFor="let driver of driverListItem$ | async" [value]="driver.id">{{ driver.firstName + ' ' + driver.lastName }}</mat-option>
  </mat-autocomplete>
</mat-form-field>

Solution

  • Have a look at the docs: https://material.angular.io/components/autocomplete/overview#setting-separate-control-and-display-values

    If you want the option's control value (what is saved in the form) to be different than the option's display value (what is displayed in the text field), you'll need to set the displayWith property on your autocomplete element. A common use case for this might be if you want to save your data as an object, but display just one of the option's string properties. To make this work, create a function on your component class that maps the control value to the desired display value. Then bind it to the autocomplete's displayWith property.

    autocomplete.component.html

    <mat-form-field style="width:100px">
        <input matInput name="assignedOperator" 
               [(ngModel)]="entity.assignedOperator" [matAutocomplete]="auto" />
        <mat-autocomplete #auto="matAutocomplete" [displayWith]="displayFn">
            <mat-option *ngFor="let driver of driverListItem$ | async" 
                        [value]="driver">{{ driver.firstName + ' ' + 
                       driver.lastName }}</mat-option>
        </mat-autocomplete>
    </mat-form-field>
    

    autocomplete.component.ts

    displayFn(driver?: DriverListItem): string | undefined {
      return driver ? `${driver.firstname} ${driver.lastname}` : undefined;
    }
    

    UPDATE 16/02/2018 7:56

    With this approach you have to set the mat-option proberty [value] to driver. This means your [(ngModel)]="entity.assignedOperator" holds your driver object.