angular和ng-zorro 可编辑表格,响应式表单,增加,删除,编辑一行,并附有校验功能
table-edit-row.component.html
<form nz-form [formGroup]="validateForm">
<button nz-button nzType="dashed" class="add-button" (click)="addRow()">
<i nz-icon nzType="plus"></i>
Add field
</button>
<button nz-button (click)="submitData()" nzType="primary">提交</button>
<br />
<br />
<nz-table [nzShowPagination]="false" nzSize="middle" #editRowTable nzBordered [nzData]="listOfData">
<thead>
<tr>
<th>Name</th>
<th>Mobile</th>
<th>Address</th>
<th nzWidth="200px">Action</th>
</tr>
</thead>
<tbody>
<ng-container formArrayName="aliases">
<tr [formGroupName]="i" *ngFor="let data of aliases.controls;let i=index" class="editable-row">
<ng-container *ngIf="editId != data.value.id; else editTemplate">
<td>
{{data.value.name}}
</td>
<td>
{{data.value.mobile}}
</td>
<td>
{{data.value.address}}
</td>
<td>
<a (click)="deleteRow(i)">delete</a>
<a (click)="startEdit(data.value)">edit</a>
</td>
</ng-container>
<ng-template #editTemplate>
<ng-container>
<td>
<nz-form-item>
<nz-form-control nzSpan="1-24" nzErrorTip="请输入姓名">
<input type="text" nz-input formControlName="name" maxlength="4" />
</nz-form-control>
</nz-form-item>
</td>
<td>
<nz-form-item>
<nz-form-control nzSpan="1-24" [nzErrorTip]="errorTpl">
<input type="text" nz-input formControlName="mobile" />
<ng-template #errorTpl let-control>
<ng-container *ngIf="control.hasError('required')">请输入电话</ng-container>
<ng-container *ngIf="control.hasError('confirm')">
请输入正确格式的电话号码
</ng-container>
</ng-template>
</nz-form-control>
</nz-form-item>
</td>
<td>
<nz-form-item>
<nz-form-control nzSpan="1-24" nzErrorTip="请输入地址">
<input type="text" nz-input formControlName="address" />
</nz-form-control>
</nz-form-item>
</td>
<td>
<a (click)="deleteRow(i)">delete</a>
<a nzType="link" (click)="saveRow()">save</a>
<!-- <a (click)="stopEdit(data.value)">cancel</a> -->
</td>
</ng-container>
</ng-template>
</tr>
</ng-container>
</tbody>
</nz-table>
<nz-pagination [nzPageSize]="10" [(nzPageIndex)]="current" [nzTotal]="listOfData.length"></nz-pagination>
</form>
table-edit-row.component.ts
import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormControl, FormGroup, FormArray, Validators } from '@angular/forms';
import { NzMessageService } from 'ng-zorro-antd/message';
interface ItemData {
id: string;
name: string;
mobile: string;
address: string;
}
@Component({
selector: 'app-table-edit-row',
templateUrl: './table-edit-row.component.html',
styleUrls: ['./table-edit-row.component.css']
})
export class TableEditRowComponent implements OnInit {
validateForm!: FormGroup;
current:number = 1;
i = 0;
rowData: object = {};
editId: string | null = null;
listOfData: ItemData[] = [{
id: '001',
name: '小明1',
mobile: '13120257131',
address: '上海',
}, {
id: '002',
name: '小明2',
mobile: '13120257132',
address: '北京',
},{
id: '003',
name: '小明3',
mobile: '13120257131',
address: '广州',
}];
startEdit(rowData: any): void {
for (const i in this.validateForm.controls) {
if (this.validateForm.controls.hasOwnProperty(i)) {
this.validateForm.controls[i].markAsDirty();
this.validateForm.controls[i].updateValueAndValidity();
}
}
if (!this.validateForm.valid) {
this.message.create('error', '只能同时编辑一行')
} else {
this.rowData = rowData;
this.editId = rowData.id;
}
}
stopEdit(row: any): void {
//取消 有bug 暂时先不显示
for (let index = 0; index < this.validateForm.value.aliases.length; index++) {
const element = this.validateForm.value.aliases[index];
if (element.id == row.id) {
this.validateForm.value.aliases[index] = this.rowData;
console.log('this.validateForm.value.aliases', this.validateForm.value.aliases)
}
}
let tempList = this.validateForm.value.aliases;
this.validateForm.patchValue({
aliases: tempList
})
this.editId = null;
}
addRow(): void {
let allowAdd = false;
for (let index = 0; index < this.validateForm.value.aliases.length; index++) {
const element = this.validateForm.value.aliases[index];
if (element.name && element.mobile && element.address) {
allowAdd = true;
} else {
allowAdd = false;
}
}
if (allowAdd) {
// if (this.validateForm.valid) {
let editId = JSON.stringify(Date.now());
this.aliases.push(this.fb.group({
id: editId,
name: ['', [Validators.required]],
mobile: ['', [Validators.required, this.confirmationValidator]],
address: ['', [Validators.required]],
}))
this.editId = editId;
} else {
this.message.create('error', '只能新增一行')
}
}
saveRow() {
// this.editId = null;
if (this.validateForm.valid) {
this.editId = null;
console.log('value', this.validateForm.value.aliases)
} else {
this.message.create('error', '请完善此行信息')
}
}
submitData() {
for (const i in this.validateForm.controls) {
if (this.validateForm.controls.hasOwnProperty(i)) {
this.validateForm.controls[i].markAsDirty();
this.validateForm.controls[i].updateValueAndValidity();
}
}
if (!this.validateForm.valid) {
this.message.create('error', '请补全信息')
}
if (this.validateForm.valid) {
console.log('submit:', this.validateForm.value.aliases)
}
}
deleteRow(index: any): void {
// console.log(index);
this.removeFormArrayItem(index);
console.log('this.validateForm.value.aliases', this.validateForm.value.aliases)
// this.listOfData = this.listOfData.filter(d => d.id !== id);
}
get aliases() {
return this.validateForm.get('aliases') as FormArray;
}
//删除表单组
removeFormArrayItem(index: any) {
this.aliases.removeAt(index);
}
// 生成唯一值
getUID() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
const r = Math.random() * 16 | 0, v = c === 'x' ? r : (r & 0x3 | 0x8);
return v.toString(16);
});
}
confirmationValidator = (control: FormControl): { [s: string]: boolean } => {
if (!control.value) {
return { required: true };
} else if (!(/^1[3456789]\d{9}$/.test(control.value))) {
return { confirm: true, error: true };
}
return {};
};
constructor(
private fb: FormBuilder,
private message: NzMessageService
) {
}
ngOnInit(): void {
this.validateForm = this.fb.group({
aliases: this.fb.array([])
})
for (let index = 0; index < this.listOfData.length; index++) {
const element = this.listOfData[index];
this.aliases.push(this.fb.group({
id: element.id,
name: [element.name, [Validators.required]],
mobile: [element.mobile, [Validators.required, this.confirmationValidator]],
address: [element.address, [Validators.required]],
}))
}
// console.log(this.validateForm)
console.log(this.aliases.controls)
}
}