我正在尝试使用最新材料+ cdk for angular来构建内联可编辑表格。
如何使用mat-table使用
[formGroupName]
,以便表单字段可以通过其正确的表单路径引用?
这是我到目前为止所得到的:Complete StackBlitz example
模板
<form [formGroup]="form">
<h1>Works</h1>
<div formArrayName="dates" *ngFor="let date of rows.controls; let i = index;">
<div [formGroupName]="i">
<input type="date" formControlName="from" placeholder="From date">
<input type="date" formControlName="to" placeholder="To date">
</div>
</div>
<h1>Wont work</h1>
<table mat-table [dataSource]="dataSource" formArrayName="dates">
<!-- Row definitions -->
<tr mat-header-row *matHeaderRowDef="displayColumns"></tr>
<tr mat-row *matRowDef="let row; let i = index; columns: displayColumns;" [formGroupName]="i"></tr>
<!-- Column definitions -->
<ng-container matColumnDef="from">
<th mat-header-cell *matHeaderCellDef> From </th>
<td mat-cell *matCellDef="let row">
<input type="date" formControlName="from" placeholder="From date">
</td>
</ng-container>
<ng-container matColumnDef="to">
<th mat-header-cell *matHeaderCellDef> To </th>
<td mat-cell *matCellDef="let row">
<input type="date" formControlName="to" placeholder="To date">
</td>
</ng-container>
</table>
<button type="button" (click)="addRow()">Add row</button>
</form>
零件
export class AppComponent implements OnInit {
data: TableData[] = [ { from: new Date(), to: new Date() } ];
dataSource = new BehaviorSubject<AbstractControl[]>([]);
displayColumns = ['from', 'to'];
rows: FormArray = this.fb.array([]);
form: FormGroup = this.fb.group({ 'dates': this.rows });
constructor(private fb: FormBuilder) { }
ngOnInit() {
this.data.forEach((d: TableData) => this.addRow(d, false));
this.updateView();
}
emptyTable() {
while (this.rows.length !== 0) {
this.rows.removeAt(0);
}
}
addRow(d?: TableData, noUpdate?: boolean) {
const row = this.fb.group({
'from' : [d && d.from ? d.from : null, []],
'to' : [d && d.to ? d.to : null, []]
});
this.rows.push(row);
if (!noUpdate) { this.updateView(); }
}
updateView() {
this.dataSource.next(this.rows.controls);
}
}
这不行。控制台产量
错误错误:找不到路径控件:'dates - > from'
似乎[formGroupName]="i"
没有效果,因为使用formArray时路径应该是dates -> 0 -> from
。
我当前的解决方法:对于这个问题,我绕过了内部路径查找(formControlName="from"
)并直接使用表单控件:[formControl]="row.get('from')"
,但我想知道我怎么能(或者至少为什么我不能)使用Reactive Form首选办法。
欢迎任何提示。谢谢。
因为我认为这是一个错误,我已经使用angular / material2 github repo注册了an issue。
我会使用matCellDef
绑定中可以得到的索引:
*matCellDef="let row; let index = index" [formGroupName]="index"
这是示例代码
在Html中:
<form [formGroup]="tableForm">
<mat-table formArrayName="users" [dataSource]="dataSource">
<ng-container cdkColumnDef="position">
<mat-header-cell *cdkHeaderCellDef> No. </mat-header-cell>
<mat-cell *cdkCellDef="let row let rowIndex = index" [formGroupName]="rowIndex">
<input type="text" size="2" formControlName="position"> </mat-cell>
</ng-container>
<ng-container cdkColumnDef="name">
<mat-header-cell *cdkHeaderCellDef> Name </mat-header-cell>
<mat-cell *cdkCellDef="let row let rowIndex = index" [formGroupName]="rowIndex">
<input type="text" size="7" formControlName="name">
</mat-cell>
</ng-container>
<ng-container cdkColumnDef="weight">
<mat-header-cell *cdkHeaderCellDef> Weight </mat-header-cell>
<mat-cell *cdkCellDef="let row let rowIndex = index" [formGroupName]="rowIndex">
<input type="text" size="3" formControlName="weight">
</mat-cell>
</ng-container>
<ng-container cdkColumnDef="symbol">
<mat-header-cell *cdkHeaderCellDef> Symbol </mat-header-cell>
<mat-cell *cdkCellDef="let row let rowIndex = index" [formGroupName]="rowIndex">
<input type="text" size="2" formControlName="symbol">
</mat-cell>
</ng-container>
<!-- Header and Row Declarations -->
<mat-header-row *cdkHeaderRowDef="displayedColumns"></mat-header-row>
<mat-row *cdkRowDef="let row; columns: displayedColumns;"></mat-row>
</mat-table>
</form>
控制器代码:
displayedColumns: string[] = ['position', 'name', 'weight', 'symbol'];
dataSource ;
tableForm: FormGroup;
constructor(private formBuilder: FormBuilder){
this.dataSource = [
{position: 1, name: 'Hydrogen', weight: 1.0079, symbol: 'H'},
{position: 2, name: 'Helium', weight: 4.0026, symbol: 'He'},
{position: 3, name: 'Lithium', weight: 6.941, symbol: 'Li'},
{position: 4, name: 'Beryllium', weight: 9.0122, symbol: 'Be'},
{position: 5, name: 'Boron', weight: 10.811, symbol: 'B'},
{position: 6, name: 'Carbon', weight: 12.0107, symbol: 'C'},
{position: 7, name: 'Nitrogen', weight: 14.0067, symbol: 'N'},
{position: 8, name: 'Oxygen', weight: 15.9994, symbol: 'O'},
{position: 9, name: 'Fluorine', weight: 18.9984, symbol: 'F'},
{position: 10, name: 'Neon', weight: 20.1797, symbol: 'Ne'},
];
}
ngOnInit(){
this.tableForm= this.formBuilder.group({
users: this.formBuilder.array([])
})
this.setUsersForm();
this.tableForm.get('users').valueChanges.subscribe(users => {console.log('users', users)});
}
private setUsersForm(){
const userCtrl = this.tableForm.get('users') as FormArray;
this.dataSource.forEach((user)=>{
userCtrl.push(this.setUsersFormArray(user))
})
};
private setUsersFormArray(user){
return this.formBuilder.group({
position:[user.position],
name:[user.name],
weight:[user.weight],
symbol:[user.symbol]
});
}