将FormArray与来自响应和mat-checkbox的对象一起使用

时间:2019-08-06 16:24:03

标签: angular typescript angular-reactive-forms

我已经全面了解了Angular Reactive表单文档,但仍在努力实现以下功能:

使用我的NgRx存储区中的一个分区列表,为每个分区中的分区名称及其选中状态(使用division.current属性-默认情况下会检查当前活动的分区)输出一个mat-复选框反应形式。

我在这里:

new-season-component.ts

export class NewSeasonComponent implements OnInit {
  chooseDivisions: FormGroup;
  divisions: FormArray;
  allDivisions: Division[];
  constructor(
      private fb: FormBuilder,
      private store: Store<AppState>
  ) {
    }
  ngOnInit() {
    this.store.dispatch(new AllDivisionsRequested());
    this.store
        .pipe(
            select(selectAllDivisions)
        ).subscribe(divisions => this.allDivisions = divisions);

    this.chooseDivisions = this.fb.group({
      divisions: this.fb.array([])
    });

    this.addDivisions();

  }
  createDivisionFormControl(division: Division): FormGroup {
    return this.fb.group({
      id: division.id,
      name: division.name,
      current: division.current
    });
  }
  addDivisions(): void {
    this.divisions = this.chooseDivisions.get('divisions') as FormArray;
    this.allDivisions.map(
        division => {
          this.createDivisionFormControl(division);
        }
    );
  }

总而言之-从商店中获取部门,创建一个包含空formArray的formGroup。然后运行一个方法来映射这些分区,然后调用另一个方法将它们创建为formGroups。

** new-season-component.html **

<form [formGroup]="chooseDivisions">
  <ng-template matStepLabel>Choose which teams are part of this season</ng-template>
  <div formArrayName="divisions">
    <div *ngFor="let division of chooseDivisions.get('divisions').controls; let i = index;">
      <div [formGroupName]="i">
        <mat-checkbox formControlName="division">{{ division[i].name }}</mat-checkbox>
      </div>
    </div>
  </div>
  <div>
    <button mat-button matStepperNext>Next</button>
  </div>
</form>

到目前为止,我已经使用了各种在线资料-包括this article,但似乎都不是我想要的东西-即在加载时添加除法列表作为复选框,而不是功能单击按钮以添加新的空白表单控件。

我显然在做一些根本错误的事情。我应该在这里使用反应形式吗?

1 个答案:

答案 0 :(得分:0)

Form数组必须始终是Form Group的子级,否则会引发错误。因此,您必须在ngOnInit中使用表单数组作为控件来初始化表单组。

this.divisionsFormGroup = this.fb.group({
    divisions: this.fb.array([])
});

我建议稍后再推入表单数组:

this.allDivisions.map(divisionFromStore => this.divisionsFormGroup.controls.divisions.push(createDivisionFormControl(divisionFromStore));

然后输入HTML:

<form [formGroup]="divisionsFormGroup">
  <ng-template matStepLabel>Choose which teams are part of this season</ng-template>
  <div formArrayName="divisions">
    <div *ngFor="let division of divisions.controls; let i = index;"> // I can't quite recall if you can call controls off of the formArrayName, or if you have to use divisionsFormGroup.controls.divisions.controls
      <div [formControlName]="i">
        <mat-checkbox>{{ division.controls.name.value }}</mat-checkbox> // Try just division.name if that doesn't work
      </div>
    </div>
  </div>
  <div>
    <button mat-button matStepperNext>Next</button>
  </div>
</form>

输入错误...

  • 保留表单组创建方法的返回值

return this.fb.group({etc}) as AbstractControl // I can't quite recall if it'll error out and say there's no overlap between properties. If that doesn't work, do the below...

  • 改为使用表单数组的setValue()

const arrayOfAllDivisionsFormGroups = this.allDivisions.map(divisionFromStore => createDivisionFormControl(divisionFromStore));

this.divisionsFormGroup.controls.divisions.setValue(arrayOfAllDivisionsFormGroups);

不应存在类型为b / c的setValue()冲突。