Nested Headers and Table in Reactive Forms

2019-01-29 09:51发布

问题:

I have several categories and each category has several materials/products. I have a problem since when i decided to delete a material/product on a category, I also delete a material/product in another category? How would able to fix this using reactive forms? How would i independently delete one material only and not another? This is the link to my code CODE LINK

patchValues() {
    let rows = this.myForm.get('rows') as FormArray;
    this.orders.forEach(material => {
      material.materials.forEach(x => {
      rows.push(this.fb.group({material_id: x.id,material_name: x.name, quantity: x.qty}))
    })
      })

  }

  onDeleteRow(rowIndex) {
    let rows = this.myForm.get('rows') as FormArray;
    rows.removeAt(rowIndex)
  }

回答1:

Well, the idea is the same,

createForm(categories:any,orders:any) //Our form has only an arrayForm "data"
  {
    return this.fb.group(
      {
        //we send orders[0].materials, orders is an array (sorry)
        data:this.fb.array(this.createOrders(categories,orders[0].materials))
      }
    )
  }
  createOrders(categories:any,materials:any) //<--received materials
  {
    //using map, with each "categories" we create a formGroup, so we return a formGroup[]
    return categories.map(x=>
    {
      return this.fb.group({  
        name: x.name,
        materials:this.fb.array(this.createMaterial(materials)) //<--call a function

      })
    })
  }


回答2:

You need create an array of array. it's easy lose yourself if you haven't careful, but it's some like:

constructor(private fb: FormBuilder) { 
    this.myForm=this.createForm(this.orders);  //I like pass the argument
  }

  createForm(orders:any) //Our form has only an arrayForm "data"
  {
    return this.fb.group(
      {
        data:this.fb.array(this.createOrders(orders))
      }
    )
  }
  createOrders(orders:any)
  {
    //using map, with each "order" we create a formGroup, so we return a formGroup[]
    return orders.map(x=>
    {
      return this.fb.group({  
        id: x.id,
        name: x.name,
        address: x.adress,
        materials:this.fb.array(this.createMaterial(x.materials)) //<--call a function

      })
    })
  }
  createMaterial(materials:any)  //like the above function return a fromGroup[]
  {
    return materials.map(x=>{
      return this.fb.group({material_id: x.id,material_name: x.name, quantity: x.qty})
    })
  }

the template it's like

    <form class="form-horizontal" [formGroup]="myForm" (ngSubmit)="onCreateProduct()" >
      <div class="card" formArrayName="data">
        <div class="card-block" 
          *ngFor="let category of myForm.get('data').controls;let i=index">
 <!--see that to show the name of categorie we are using the array categories
     this are not included in the myForm, it's the "variable" categories-->
        CATEGORY:   {{ categories[i].name }}  
        <br>
          <table class="table" [formGroupName]="i" >
            <thead>
              <tr>
                <th>Material ID</th>
                <th>Material Name</th>
                <th>Qty</th>
                <th>Action</th>
              </tr>
            </thead>
            <tbody formArrayName="materials">
              <tr *ngFor="let row of category.get('materials').controls; let j = index" [formGroupName]="j">
                <td>{{row.value.material_id}}</td>
                <td>{{row.value.material_name}}</td>
                <td>{{row.value.quantity}}</td>
                <td><button type="button" (click)="onDeleteRow(i,j)"> <i class="icofont icofont-ui-delete"></i> Remove</button></td>
              </tr>
            </tbody>

          </table>
        </div>
      </div>
    </form>