【问题标题】:mat table with dynamically adding rows and editable fields in a row with validatons使用验证在一行中动态添加行和可编辑字段的 mat 表
【发布时间】:2020-01-29 00:28:38
【问题描述】:

我刚刚开始研究 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 不是函数

【问题讨论】:

  • 你有没有重现错误的 stackblitz 链接?
  • 您在stackoverflow.com/questions/56566003/… 和 cmets 中有一个示例。如果您想要一个更复杂的示例,了解如何使用箭头键添加/删除行和跨输入移动 stackblitz.com/edit/…
  • @Eliseo,我怎样才能使 myformArray = new FormArray([ 动态的。因为我正在从后端获取数据。从 stackoverflow 链接
  • 我把它作为回应,评论没有足够的空间:)

标签: javascript angular angular7 angular-reactive-forms angular-material-7


【解决方案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")
}

这种方法的好处是你只需要 make 就可以向 FormArray 添加一个新元素

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

【讨论】:

  • stackblitz.com/edit/angular-mqqv3d 我做了一些更改,但我对 html 部分有疑问,请您帮忙@Eliseo
  • 只是将服务更改为返回数据并将formArray.controls用作数据源,请参阅您的分叉stackblitz。stackblitz.com/edit/…有错误,但我很着急
  • 我面临的最后一个问题是,我已经用表格包裹了表格,并在最后放置了一个提交按钮。 formArray 未显示表单的正确有效状态。如果一旦 fromArray.valid 变为假,即使我提供了正确的细节,它也不会变为真。新添加的行是可选的,但是一旦您提交了一些值,那么整个行就成为必需的。但是 formArray.valid 不起作用。单独的控件工作正常。
  • stackblitz.com/edit/… 或 stackblitz.com/edit/angular-mqqv3d 代码更新@Eliseo
  • 你能帮忙把表格包装成一个表格吗,因为我有一些与表格标签有关的验证?
猜你喜欢
  • 2017-02-09
  • 1970-01-01
  • 1970-01-01
  • 2014-12-19
  • 2020-11-15
  • 2020-06-13
  • 1970-01-01
相关资源
最近更新 更多