mat table 动态添加行和 editable 字段

mat table with dynamically adding rows and editable fields in a row with validatons

我刚刚开始研究 Angular 响应式表单,我试图构建一个表单内的 table。

table 已添加新功能,单击它会在 table 中插入新的空行。默认情况下,现有行将处于编辑模式,并且它们已被验证。 table 数据将通过单个保存按钮保存,该按钮位于 table 之外但位于表单内。 我试过下面的代码

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 不是函数

如何从数据中创建一个 formArray

假设您有这样的数据

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

要创建一个 formArray 它很有用,它有一个函数,它接收一个对象和 return 一个 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)
   })
}

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

有了数据就可以做简单的事情

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

这就是数据的每个元素转换为一个formGroup,formArray将是一个包含这些元素的数组。 map 变换 "this.createFormGroup(x)"

中的每个元素 "x"

如果您有一项服务 return 您订阅的数据

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)))