嵌套角反应形式和发现控制的错误

时间:2019-01-02 22:00:36

标签: angular checkbox angular-reactive-forms

我想在Angular中创建一个可以提交对象数组的表单。

因此,我想得到一个这样的Json:

order = {
 selectedDays: [{
  meals: [
    {name: 'breakfast',
    selected: false},
    {name: 'dinner',
    selected: false},
    {name: 'supper',
    selected: false}
  ],
  selectedDay: "10/01/2018"
}
]}

但是,我在找到控件时遇到了一些问题。我收到此错误:

  

错误:找不到路径为“ selectedDays-> 0->餐点->早餐”的控件

这是我的代码:

HTML:

<div class="" [formGroup]="form">
 <button (click)="addNewDay()">Dodaj nowe zamówienie</button><br><br>
  <div class="row" formArrayName="selectedDays">
    <div *ngFor="let day of form.get('selectedDays').controls; let i=index">
      <fieldset>
        <legend><h3>Chosen day {{i+1}}: </h3></legend>
          <div [formGroupName]="i">
            <div class="col-md-3">
              <h5>Choose date</h5>
              <mat-form-field >
                  <input matInput formControlName="selectedDate" [matDatepicker]="picker">
                  <mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle>
                  <mat-datepicker #picker></mat-datepicker>
              </mat-form-field>
            </div>
            <div class="col-md-3" formArrayName="meals">
              <div><mat-checkbox formControlName="breakfast"> breakfast </mat-checkbox> </div>
              <div><mat-checkbox formControlName="dinner"> dinner </mat-checkbox> </div>
              <div><mat-checkbox formControlName="supper"> supper  </mat-checkbox> </div> 
            </div>     
          </div>
      </fieldset>
  </div>
</div>
<button click="submit()">Send order</button>

<pre>Form values: {{form.value | json}}</pre>

和打字稿:

export class OrderFormComponent implements OnInit {

public form: FormGroup;
public availableMeals: string[] = [
  "breakfast", "dinner", "supper"
];

order = {
  selectedDays: [
    {
      meals: [
        {name: 'breakfast',
        selected: false},
        {name: 'dinner',
        selected: false},
        {name: 'supper',
        selected: false}
      ],
      selectedDay: "10/01/2018"
    }
  ]
}
  
constructor(private orderService: OrderService,
            private formBuilder: FormBuilder) { 
  this.form = this.formBuilder.group({
    selectedDays: this.formBuilder.array([])
  })
 
  this.setSelectedDays();
}

addNewDay() {
  let control = <FormArray>this.form.controls.selectedDays;
  control.push(
    this.formBuilder.group({
      meals: this.formBuilder.array([]),
      selectedDate: new FormControl((new Date()))
    })
  )
}

setSelectedDays() {
  let control = <FormArray>this.form.controls.selectedDays;
  this.order.selectedDays.forEach(x => {
    control.push(this.formBuilder.group({ 
      meals: this.mapToCheckboxArrayGroup(this.availableMeals),
      selectedDate: x.selectedDay
    }))
  })
}

submit() {
  this.orderService.sendOrder(this.form.value).subscribe(() => {
      console.log("Order added");
    },
    err => {
      console.log('error occurred: ' + err.message);
    }
  );
}

private mapToCheckboxArrayGroup(data: string[]): FormArray {
  return this.formBuilder.array(data.map((meal) => {
    return this.formBuilder.group({
      name: meal,
      selected: false
      });
    }));
  }
}

我的Day.ts对象:

export interface Day {
    meals: [
        {name: 'breakfast',
        selected: boolean},
        {name: 'dinner',
        selected: boolean},
        {name: 'supper',
        selected: boolean}
    ]
    selectedDay: string;
  }
  

可能我错过了一些东西,但是我不能自己解决它-我对Angular很陌生。我将感谢您的帮助!

1 个答案:

答案 0 :(得分:1)

因此,在创建my own version of this之后。有几件事要讨论。首先是您在以下代码中使用formControlName

<div class="col-md-3" formArrayName="meals">
    <div><mat-checkbox formControlName="breakfast"> breakfast </mat-checkbox> </div>
    <div><mat-checkbox formControlName="dinner"> dinner </mat-checkbox> </div>
    <div><mat-checkbox formControlName="supper"> supper  </mat-checkbox> </div> 
</div>

问题是您的控件没有名称。如果您在控制台中拉出表单,您会注意到它变成FormGroup -> Controls -> Meals -> Controls -> 0-3。您必须再次遍历它们,然后尝试从对象本身中拉出名称。 这真的很困难,至少对我来说是如此。相反,您可能想像为selectedDays一样向数组的索引分配一个变量,然后使用迭代器访问{{1}的meals属性}。

如果这样做,最终将不得不对各种复选框进行硬编码,然后选择order.selectedDays[i],它将自动提取信息,并在{中附加*ngFor属性的值{1}通过selected进入复选框。

查看我链接到的StackBlitz示例,我知道它在设计方面看起来完全不同,但是正在使用我提到的方法。您希望查看上述迭代方法的控件是order.selectedDays[i].meals[m]控件,请注意,在该控件中,我使用了[(ngModel)],这使我可以使用order-form