【问题标题】:Using FormArray with objects from response and mat-checkbox将 FormArray 与来自响应和 mat-checkbox 的对象一起使用
【发布时间】:2019-12-14 06:15:01
【问题描述】:

在完全消化了 Angular Reactive 表单文档后,我仍在努力实现以下功能:

使用我的 NgRx 存储中的分区列表,在 Angular 内为每个分区名称输出一个 mat-checkbox 并检查状态(使用 division.current 属性 - 以便默认检查当前活动的分区)反应形式。

这是我所在的位置:

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 但似乎没有一个是我正在寻找的 - 即在加载时添加一个部门列表作为复选框,而不是单击的功能用于添加新的空白表单控件的按钮。

我显然在做一些根本错误的事情。我是否应该在这里使用响应式表单?

【问题讨论】:

  • 表单数组中的表单组内没有名为division 的表单控件。表单控件被命名为 id、name 和 current。所以formControlName="division" 不正确。
  • division[i] 也不正确:除法是一个FormGroup。
  • @JBNizet 你有可以回答的工作版本吗?

标签: angular typescript angular-reactive-forms


【解决方案1】:

表单数组必须始终是表单组的子元素,否则会抛出错误。因此,您必须在 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() 需要 any[]

【讨论】:

  • 嗯 - 我已经有一个表单组,里面有表单数组 - chhoseDivisions -> 部门。当我使用您的代码推入数组时,我还收到错误“AbstractControl”类型上不存在“Property 'push'”
  • 好的。因此,在模板和组件中看到 DivisionsFormGroup 的任何地方,都替换为 chooseDivisions。键入问题的解决方法是将 createDivisionFormControl 的返回值转换为 AbstractControl。如果不想这样做,可以使用表单数组的 setValue。我会在上面放一些代码。
猜你喜欢
  • 1970-01-01
  • 2019-10-09
  • 2012-06-17
  • 2019-10-25
  • 2013-09-11
  • 2020-10-12
  • 2019-05-26
  • 1970-01-01
  • 2023-03-29
相关资源
最近更新 更多