Search code examples
angularangular-forms

How to use full objects in Angular reactive forms


I am updating some old angular forms and have an issue with setting the form to an entire instance of an object while also being able to set the initial value.

I have tried setting the [value]="option" to the entire object while having {{ option.$type }} but the initial value doesn't show up. I have also tried using [ngValue] but I get an error even when I import ReactiveFormModule

Current code:

<mat-form-field fxFlex="49">
    <mat-select placeholder="Type" formControlName="type" autocomplete="off" required>
        <mat-option *ngFor="let option of container$ | async" [value]="option.$type">{{ option.$type }}
        </mat-option>
    </mat-select>
</mat-form-field>

I would prefer to have the whole container object as the value so I am able to access the option.$id later, but

this.editContainerForm.controls['type'].setValue(this.containerContext.$containerTypeName );

stops working even if i set the form with the entire container object.


Solution

  • Object are compared by reference in that case in order to use object as value must be the same reference

    this mean

    const a = {type$ : 'A'};
    const a2 = {type$:'A'}; 
    
    console.log(a === a2); // false 
    

    if you try to use object both object has to be the same refrence

      const a = {type$ : 'A'};
      const a2 = a; 
    
      console.log(a === a2); // true
    

    basic example

      form:FormGroup;
      container$;
    
      data = [
          {$type:'A'},
          {$type:'B'},
          {$type:'C'},
        ]
      constructor(fb:FormBuilder) {
        this.form = fb.group({
          type:this.data[1]
        })
    
        this.container$ = of(this.data)
      }
    

    as you can see type has a value of the same refrence check the stackblitz demo 🔥🔥

    Updated! ✨

    you can provide [compareWith][2] a function to compare the option values with the selected values. The first argument is a value from an option. The second is a value from the selection. A boolean should be returned.

      compareWith(value , selectedValue ) {
        return value.$type === selectedValue.$type
      }
    

    template

    <mat-select placeholder="Type" formControlName="type" autocomplete="off" required [compareWith]="compareWith">
        <mat-option *ngFor="let option of container$ | async" [value]="option" >{{ option.$type }}
        </mat-option>
    </mat-select>
    

    stackblitz demo 🔥🔥