Search code examples
angularangular-reactive-formsangular4-forms

After Patching Select Value From Dropdown


I have this list of ingredients that has their specific Unit of Measurements. However, each ingredient has two unit of measurement. The first_unit and the second_unit. How can i transfer it after patching value OR after selecting the ingredient? How can i filter out the unit of measurement dropdown according to its ingredient? Here;'s my stackblitz link

https://stackblitz.com/edit/form-array-patch-mtiiee?file=app/app.component.ts

patchValues(id,i) {
    let x = (<FormArray>this.addForm.controls['rows']).at(i);
    console.log(x);

    x.patchValue({
      unit_price: this.ingredients[id - 1].price,
      uom: this.ingredients[id - 1].first_unit.name,
      // uom: this.ingredients[id - 1].second_unit.name
    });
  }

Solution

  • If we have a form that some fields depending the value of an object, it's usefully that the value of a control was the own object, not only the "id" of the object So, You can have a fbgroup with ingredientData, not with "id". Well, when you send the data to a service, not send the ingredientData, only the "id"

    initGroup() {
        let rows = this.addForm.get('rows') as FormArray;
        rows.push(this.fb.group({
          ingredientData: ['', Validators.required], //<--see that not is ingredient_id
          unit_price: new FormControl({ value: '', disabled: true }, Validators.required),
          uom: ['', Validators.required],
        }))
    }
    

    Then your form will be like

    <select class="form-control" formControlName="ingredientData">
       <option value="null" hidden>-- Select Ingredient --</option>
       <option *ngFor="let ingredient of ingredients" [ngValue]="ingredient">{{ingredient.name}}</option>
    </select>
    
    <select class="form-control" formControlName="uom">
       <option value="null" hidden>-- Select Unit of Measure --</option>
       <option *ngIf="row.value.ingredientData" [value]="row.value.ingredientData.first_unit.id">
           {{row.value.ingredientData.first_unit.name}}
       </option>
       <option *ngIf="row.value.ingredientData" [value]="row.value.ingredientData.second_unit.id">
           {{row.value.ingredientData.second_unit.name}}
       </option>
    </select>
    

    in un submit, we must "mappear" the response like

    onSubmit(){
        const data = {
          ingredient: this.addForm.get('rows').value.map((x)=>{
            //from each row, we create a new object
            return {
               id:x.ingredientData.id,
               unit_price:x.ingredientData.price,
               uom:x.uom
            }
          })
        }