1

我刚刚开始研究 Angular 反应式表单,我正在尝试构建一个表单内的表。

该表通过单击添加了新功能,新的空行将插入到表中。默认情况下,现有行将处于编辑模式并经过验证。表格数据将使用单个保存按钮保存,该按钮不在表格中但在表格内。我尝试了下面的代码

constructor(private router: Router, private fb: FormBuilder) { }
  columnsToDisplay: string[];
  dataList;
  copyDataList;
  rows: FormArray = this.fb.array([]);
  formGroup: FormGroup = this.fb.group({ actualsVolumeData: this.rows });

  ngOnInit() {
    this.columnsToDisplay = ['id', 'code', 'desc'];

    this.formGroup = this.fb.group({
      columns: this.columnsToDisplay,
    });
    this.copyDataList = [];
    this.dataList = [];
    let list = [
      {
        code: 'one',
        desc: 'One1',
        id: 1
      },
      {
        code: 'two',
        desc: 'Two1',
        id: 2
      },
      {
        code: 'three',
        desc: 'Three1',
        id: 3
      },
    ];
    this.copyDataList = new MatTableDataSource(list);
    this.dataList = new MatTableDataSource(list);
  }

  onAdd() {
    let newRow = {
      id: this.dataList.data.length + 1,
      code: undefined,
      desc: undefined
    }
    this.copyDataList.data.push(newRow);
    this.dataList = new MatTableDataSource(this.copyDataList.data);
  }

  onSubmit() {

  }
<form [formGroup]=`formGroup`>
  <button mat-button (click)=`onAdd()`>Add</button>
  <table mat-table [dataSource]=`dataList` [formArrayName]=`actualsVolumeData` class=`mat-elevation-z8`>

    <ng-container matColumnDef=`id`>
      <th mat-header-cell *matHeaderCellDef> ID </th>
      <td mat-cell *matCellDef=`let element, let i = index` [formGroupName]=`i`> {{element.id}} </td>
    </ng-container>

    <ng-container matColumnDef=`code`>
      <th mat-header-cell *matHeaderCellDef> Code </th>
      <td mat-cell *matCellDef=`let element, let i = index` [formGroupName]=`i`> {{element.code}}
        <mat-form-field>
          <input matInput formControlName='code'>
        </mat-form-field>
      </td>
    </ng-container>

    <ng-container matColumnDef=`desc`>
      <th mat-header-cell *matHeaderCellDef> Description </th>
      <td mat-cell *matCellDef=`let element, let i = index` [formGroupName]=`i`> {{element.desc}}
        <mat-form-field>
          <input matInput formControlName=`desc`>
        </mat-form-field>
      </td>
    </ng-container>

    <tr mat-header-row *matHeaderRowDef=`columnsToDisplay`></tr>
    <tr mat-row *matRowDef=`let row; columns: columnsToDisplay;`></tr>
  </table>
<button mat-button (click)=`formGroup.valid && onSubmit()`>submit</button>
</form>

但我收到此错误 this.validator is not a function

4

1 回答 1

1

如何从数据中创建一个formArray

想象一下你有一个像

[
 {code: 'one',desc: 'One1',id: 1},
 {code: 'two',desc: 'Two1',id: 2},
 {code: 'three',desc: 'Three1',id: 3}
]

要创建一个 formArray,有一个函数很有用,它接收一个对象并返回一个 FormGroup

createFormGroup(data):FormGroup
{
   data=data|| {code:'',desc:'',id:0}
   return new FormGroup({
       code:new FormControl(data.code,Validators.required),
       desc:new FormControl(data.desc,Validators.required),
       id:new FormControl(data.id,Validators.required)
   })
}

如果我们用一个对象调用函数返回一个formGroup,如果我们用null调用函数,也返回一个元素为空的FormGroup

当您拥有数据时,您可以做简单的事情

this.myFormArray=new FormArray(this.data.map(x=>this.createFormGroup(x)))

那就是将数据的每个元素转换为一个formGroup,formArray将是一个包含这些元素的数组。映射变换“this.createFormGroup(x)”中的每个元素“x”

如果您有一项服务可以返回您订阅的数据

this.myService.getData().subscribe(res=>{
     this.myFormArray=new FormArray(res.map(x=>x.this.createFormGroup(x)))
})

//你的服务有一个类似的方法

getData()
{
     return this.httpClient("http:myUrl")
}

这种方法的好处是要向 FormArray 添加一个新元素,您只需要 make

this.formArray.push(this.createFormGroup(null)) 

去除

this.formArray.removeAt(index)

stackblitz中有一个小例子。好吧,在服务中,我使用的 rxjs 运算符of通常是 httpClient.get(url)。只有我把创建formArray的部分,

注意:我使用 FormGroup 的构造函数和 FormArray 的构造函数,但您可以使用 BuilderForm 之类的

createFormGroup(data):FormGroup
{
   data=data|| {code:'',desc:'',id:0}
   return this.fb.group({
       code:[data.code,Validators.required],
       desc:[data.desc,Validators.required],
       id:[data.id,Validators.required]
   })
}

并使用

myFormArray=this.fb.array(res.map(x=>x.this.createFormGroup(x)))
于 2019-09-29T16:50:49.893 回答