【问题标题】:Angular-FormArray: Creating a table form from 2-dimensional Javascript arrayAngular-FormArray:从二维 Javascript 数组创建表格
【发布时间】:2020-02-13 14:02:37
【问题描述】:
  • 我需要使用 Angular 创建一个基于简单二维数组数组的表格。
  • 数据结构简单,但单元格中的数据相互依赖。单个单元格仅通过索引访问,例如 row:1col:0
  • 需要在单元级别定义自定义验证器。此外,可能还有行和列的验证器。

我尝试了各种方法来定义 FormArray 持有 FormControls 的数组。但我不确定如何在 Angular 模板中单独按行和列索引访问各自的 FormControl

型号

[
  ['a', 'b'],
  ['c', 'd']
]

表单组

  form = new FormGroup({
    rows: new FormArray([...])
  });

预期结果

我尝试了各种类似的事情:

  <form [formGroup]="form"">
    <div formArrayName="rows">
      <div 
        *ngFor="let row of rows.controls; let rowIndex = index" [formGroupName]="rowIndex">
        <div formArrayName="cols">
          <div
            *ngFor="let col of form.get('cols').controls; let colIndex = index"
            [formGroupName]="colIndex">
            <input [formControlName]="colIndex" />
          </div>
        </div>
      </div>
    </div>
  </form>

【问题讨论】:

标签: javascript arrays angular formarray


【解决方案1】:

Dabbel,如果你有一个 Array of Array,请创建一个 FormArrays of FormArrays(不好意思开个玩笑)

好吧,假设你有 数据=[ ['a', 'b'], ['c', 'd'] ]

你可以在 ngOnInit 中创建 FormArray 之类的 FormArray

//At firs a empty FormArray
this.formArray = new FormArray([]);
//with each element of data
this.data.forEach(x => {
  //x is e.g.['a','b']
  //we create a emptt FormArray
  const obj = new FormArray([]);
  //add a FormControl
  x.forEach(y => {
    obj.push(new FormControl(y));
  });
  //and push in the formArray
  this.formArray.push(obj);
});

或使用类似地图的缩写

this.formArray=new FormArray(
  this.data.map(x=>new FormArray(
    x.map(y=>new FormControl(y))))
)

那么,如何在 FormGroup 之外管理 FormArray?如果我们的FormArray是FormGroup的FormArray,我们一般做

 <!--yes we can use [formGroup] with a FormArray-->
<form [formGroup]="formArray">
   <!--iterate over the formArray.controls, that is a formGroup-->
  <div *ngFor="let group of formArray.controls;let i=index">
     <div [formGroup]="group">
       <input formControlName="name">
        ...
     </div>
  </div>
</form>

好吧,我们的 formArray 是 FormArray 的 FormArray,但请记住,我们将 [formGroup] 与数组一起使用并遍历 formArray.controls。

<form [formGroup]="formArray">
    <div *ngFor="let subarray of formArray.controls;let i=index">
        <div [formGroup]="subarray">
            <ng-container *ngFor="let control of subarray.controls;let j=index">
                <input [formControl]="control">{{control.invalid?"*":""}}
       </ng-container>
        </div>
    </div>
</form>

注意:我使用 &lt;ng-container&gt;&lt;div&gt; 不创建附加 div。 (我们不能将 *ngFor 放在自己的输入中,因为这样我们就无法访问 control.invalid

好吧,既然您想创建验证器,我们在创建 formGroup 以包含验证器时进行了一些更改,我放了一个“傻瓜”示例

this.formArray=new FormArray(
  this.data.map(x=>new FormArray(
    x.map(y=>new FormControl(y,Validators.required)),
    this.rowValidator())),this.arrayValidator()
)

我们的验证器可以像

  rowValidator()
  {
    return (array:FormArray)=> {
      const invalid:boolean=array.value.
             filter((x,index)=>array.value.indexOf(x)!=index).length>0
      return invalid?{error:'must be different'}:null
    }
  }
  arrayValidator()
  {
      return (array:FormArray)=> {
        let arrayJoin="";
        array.value.forEach(x=>arrayJoin+=x.join(''))
        return arrayJoin=="abcd"?null:{error:'must be a,b,c,d'}
      }
  }

你可以在stackblitz看到

注意:在实际应用中,我们不需要使用这么多的验证器。考虑此验证器对应用性能的影响

【讨论】:

  • 感谢您的详尽解释,Eliseo!当然,您对 FormArray 的 FormArray 是正确的。为了其他人的利益,我只想提一下,在这个例子中formArray.statusformArray.invalid 也可以与FormArray 一起使用。再次感谢您详细解释。
【解决方案2】:

模板表格将使您的生活在这里变得更轻松。

只需直接绑定到数组本身。

<form>
  <div *ngFor="let row of data;let i=index">
    <input [name]="prop1_ + i" [(ngModel)]="row.prop1">
    <input [name]="prop2_ + i" [(ngModel)]="row.prop2">
  </div>
</form>

【讨论】:

    猜你喜欢
    • 2018-01-18
    • 2021-06-16
    • 2021-04-28
    • 2013-02-16
    • 1970-01-01
    • 2019-10-16
    • 2016-12-27
    • 1970-01-01
    相关资源
    最近更新 更多