angularrxjs

How to get full item property from dropdown formControl valueChanges?


What i want is some guidance/suggestion on usage of the formControl.valueChanges. When an item is selected from a drop-down box, i want to be able to access the full item of the selected item, and not just the itemID, when using the valueChanges

my current scenario are like so:

// component.ts
interface SomeItem {
  id: number;
  name: string;
}

someIDFormControl = new FormControl(0)
someData$: Observable<SomeItem[]> = this._someService.getAll()

selectedItem$ = this.someIDFormControl.valueChanges.pipe(
  map(itemID => {
    // how can i get the full item property from here
  })
)
<select [formControl]="someIDFormControl">
  <option *ngFor="let item of (someData$|async)" [value]="item.id">{{ item.name }}</option>
</select>

with following requirements:


Simply based on what I currently know, the only idea i got is to pipe the someData$ with shareReplay(), then combine with switchMap\map pipe. But this would require additionally find again from the array which doesn't seems ideal(?).

example:

someData$: Observable<SomeItem[]> = this._someService.getAll().pipe(shareReplay(1))
selectedItem$ = this.someIDFormControl.valueChanges.pipe(
  switchMap(id => {
    return this.someData$.pipe(map(itemArr => itemArr.find(item => item.id === id)))
  })
)

Solution

  • Instead of [value] you can use [ngValue], that will give whole object in valueChanges. [value] gives you output in string format whereas [ngValue] gives output in object format

    HTML

    <select [formControl]="someIDFormControl">
      <option *ngFor="let item of options" [ngValue]="item">
        {{ item.name }}
      </option>
    

    TS

    interface SomeItem {
      id: number;
      name: string;
    }
    export class AppComponent {
      options = [
        {
          id: 1,
          name: 'abc',
        },
        {
          id: 2,
          name: 'xyz',
        },
      ];
    
      someIDFormControl = new FormControl<SomeItem | null>(null);
    
      constructor(private formBuilder: FormBuilder) {}
    
      ngOnInit(): void {
        this.someIDFormControl.valueChanges.subscribe((value) => {
          console.log(value);
        });
      }
    }
    

    Stackblitz link here