问题
I've tried trying to remove a row using a button click, but it doesn't work and I'm not so sure what can I do to solve this issue.
Initial json displayed is:
{ "list": [ { "description": null, "status": false } ] }
When I click the Remove button, the json displayed will become:
{ "list": [] }
AND the selected row is not removed at all.
Here's the codes below.
todo-list.component.ts
todoListForm: FormGroup;
constructor(private toDoService: TodoService, private formBuilder: FormBuilder) {
this.createForm();
}
tableData: TableData[] = [
{ id: 'aaaaa', description: 'Go to market', status: true },
{ id: 'bbbbb', description: 'Buy groceries', status: true },
{ id: 'ccccc', description: 'Order pizza delivery', status: false },
];
ngOnInit(): void { }
createForm() {
this.todoListForm = this.formBuilder.group({
list: this.formBuilder.array([])
});
this.addList();
}
get list(): FormArray {
return this.todoListForm.get('list') as FormArray;
}
addList(): void {
const addTodoListForm = this.formBuilder.group({
description: [null, Validators.required],
status: [false]
});
this.list.push(addTodoListForm);
console.log('addTodoListForm', addTodoListForm);
console.log('list', this.list);
}
removeRow(i: number): void {
console.log(this.list);
this.list.removeAt(i);
}
}
export interface TableData {
id: string,
description: string,
status: boolean,
}
todo-list-component.html
<h1> To-do List </h1>
{{ todoListForm.value | json}}
<form [formGroup]="todoListForm">
<div formArrayName="list">
<div class="tableFlex">
<table class="table table-striped" table-layout="fixed">
<tr>
<th> #ID </th>
<th> Description </th>
<th> Action </th>
</tr>
<tr *ngFor="let data of tableData, let i = index">
<td> {{ i + 1 }} </td>
<td> <del *ngIf="data.status === true">{{data.description}}</del>
<div *ngIf="data.status === false">{{data.description}}</div>
</td>
<td>
<div class="btn-toolbar pull right">
<div class="btn-group mr-2" role="group" aria-label="Mark-as">
<button type="button" class="btn btn-secondary" (click)="updateStatus(i, data.status)">
{{ data.status === true ? 'Mark as incomplete' : 'Mark as completed' }} </button>
</div>
<div class="btn-group mr-2" role="group" aria-label="Remove">
<button type="submit" class="btn btn-danger" (click)="removeRow(i)">
Remove
</button>
</div>
</div>
</td>
</tr>
</table>
</div>
</div>
</form>
回答1:
try this out by adding change detector ref
constructor(private readonly changeDetectorRef: ChangeDetectorRef){
}
removeRow(i: number): void {
this.list.removeAt(i);
this.changeDetectorRef.markForCheck();
}
if this doesn't work try this.detectChanges() as well. If this also not work ur changes are running out of the ng Zone then u can try out below thing
removeRow(i: number): void {
this.zone.run(() => this.list.removeAt(i););
}
inject Zone to this file as well
回答2:
You has a FormArray (and add elements to the formArray and remove from this), BUT you are iterating over tableData, this has no sense
First create a function that return a formGroup (more like than your addList)
createGroup(data=null)
{
data=data || {} as TableData
return this.formBuilder.group({
id:[data.id],
description: [data.description, Validators.required],
status: [data.status]
});
}
When you create the formGroup you can use this fucntion as
this.todoListForm = this.formBuilder.group({
list: this.formBuilder.array(this.tableData.map(x=>this.createGroup(x))
});
See how transform the array tableData in an array of FormGroup using map
When you iterate iterate over list.controls
<tr *ngFor="let data of list.controls, let i = index" [formGroupName]="i">
<!--use list.at(i).get('description').value-->
{{list.at(i).get('description').value}}
<!-- and list.at(i).get('status').value, e.g.-->
<div *ngIf="list.at(i).get('status').value"></div>
</tr>
And forget the ngZone, changeDetectorRef and another "strange things"
来源:https://stackoverflow.com/questions/64003106/angular-9-0-formgroup-and-formarray-remove-row-from-table