skip to Main Content

I have an autocomplete in my angular reactive form.
I want to display myObject.name but use myObject.id as value.

When the form is prefilled with existing values, I need to get myObject.name base on myObject.id which takes some time. So unfortunately, what is shown in the autocomplete is an id and not a name. I can’t make it work.

I tried with observable but it looks like displayWith does not support it. How can I do that ?

Typescript :

    public displayWith(id: string): string {
    if (!id) {
        return '';
    }
    let freespinName = '';
    this.freespins$.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(freespins => {
        const found = freespins.find((freespin: Freespin) => freespin.id === id);
        freespinName = found?.name || id;
    });

    return freespinName;
}

HMTL :

                     <mat-label>Freespin</mat-label>
                        <input type="text"
                               placeholder="Select a freespin"
                               matInput
                               formControlName="rewardId"
                               [matAutocomplete]="auto">
                        <mat-autocomplete requireSelection #auto="matAutocomplete"
                                          [displayWith]="displayWith.bind(this)">
                            <mat-option *ngFor="let freespin of filteredFreespins[i] | async"
                                        [value]="freespin.id">
                                {{freespin.name}}
                            </mat-option>
                        </mat-autocomplete>
                    </mat-form-field>

2

Answers


  1. Please write this code on ngOnInit, we need to make the API call inside displayWith

    Note this is just pseudo code, but you can use this approach and try to fix your issue!

    export class SomeComponent {
    
        nameIdMap = {};
        
        ngOnInit() {
        
            this.freespins$.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(freespins => {
                    this.nameIdMap = {};
                    // creating this hashmap will ensure that you will immediately get the value of name
                    freespins.forEach((freespin: any) => {
                        this.nameIdMap[freespin.id]=freespin.name;
                    });
                });
        
        }
        
        diplayWith(id: string): string {
            return this.nameIdMap?.[id]?.name
        }
    
    }
    
    Login or Signup to reply.
  2. If you are using angular 16+ you can use signals here

      private freespins = toSignal(this.freespins$);
    
    displayFn(id: string) => string {
            return this.freespins()!.find((freespin) => freespin.name === id)?.name || '';
          }
    

    you can also return function like this

      displayFn(): (freespins: any) => string {
        return (id: string) =>
          this.freespins()!.find((freespin) => freespin.name === id)?.name ||
          '';
      }
    

    Also if this.freespins$ is BehaviourSubject you can get the value without subscribing

    private freeSpins$ = new BehaviorSubject(this.options);
      displayFn2(user: User): string {
        return (
          this.freeSpins$
            .getValue()!
            .find((freespin) => freespin.name === user.name)?.name || ''
        );
      }
    

    check the example here
    https://stackblitz.com/edit/bdx7mn?file=src%2Fexample%2Fautocomplete-display-example.ts,src%2Fexample%2Fautocomplete-display-example.html

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search