Reputation: 1295
I have a editable PrimeNG table bound with reactive forms (not with ngtemplate). If I click edit of a single row, all rows turns into edit mode. Here is the image explaining my issue.
The prob is with the dataKey used with PrimeNg Edit table. I have no clue what to bind with dataKey, when using reactive forms.
Here is the minimal code explaining the issue.
HTML.ts
<div class="card">
<div class="card-header">
<h5>Reactive Forms with PrimeNg Table</h5>
</div>
<div class="card-body">
<form [formGroup]="employeeForm">
<p-table [value]="tableRowArray.controls" [responsive]="true" dataKey="name" editMode="row"
responsiveLayout="scroll" dataKey="name"> <!--dataKey is set wrongly-->
<ng-template pTemplate="header">
<tr>
<ng-container *ngFor="let col of columns">
<td>{{col}}</td>
</ng-container>
</tr>
</ng-template>
<ng-template pTemplate="body" let-rowData let-rowIndex="rowIndex" let-editing="editing">
<ng-container formArrayName="tableRowArray">
<tr [formGroupName]="rowIndex" [pEditableRow]="rowData">
<td style="text-align:center">
<button *ngIf="!editing" pButton pRipple type="button" pInitEditableRow icon="pi pi-pencil" class="p-button-rounded p-button-text"></button>
<button *ngIf="editing" pButton pRipple type="button" pSaveEditableRow icon="pi pi-check" class="p-button-rounded p-button-text p-button-success mr-2"></button>
<button *ngIf="editing" pButton pRipple type="button" pCancelEditableRow icon="pi pi-times" class="p-button-rounded p-button-text p-button-danger"></button>
</td>
<td>
<p-cellEditor>
<ng-template pTemplate="input"></ng-template>
<ng-template pTemplate="output">
<input type="text" class="form-control form-control-sm"
formControlName="name" />
<div class="text-danger"
*ngIf="rowData.get('name').errors && (rowData.get('name').dirty || rowData.get('name').touched)">
<div *ngIf="rowData.get('name').errors?.required">Name is Required</div>
</div>
</ng-template>
</p-cellEditor>
</td>
</tr>
</ng-container>
</ng-template>
</p-table>
</form>
</div>
<div class="card-footer">
<button type="button" class="btn btn-primary btn-sm pull-left" (click)="addNewRow()">Add Row</button>
<button type="button" class="btn btn-success btn-sm pull-right" title="Save">Save</button>
</div>
</div>
Component.ts
import { Component, OnInit } from '@angular/core';
import { FormGroup, FormBuilder, FormArray, FormControl, Validators } from '@angular/forms';
@Component({
selector: 'app-add-employee',
templateUrl: './add-employee.component.html'
})
export class AddEmployeeComponent implements OnInit {
employeeForm: FormGroup;
columns: string[];
constructor(private formBuilder: FormBuilder) {
this.columns = ["Edit", "Name"];
}
ngOnInit(): void {
this.createForm();
}
get tableRowArray(): FormArray {
debugger;
return this.employeeForm.get('tableRowArray') as FormArray;
}
addNewRow(): void {
this.tableRowArray.push(this.createTableRow());
}
onDeleteRow(rowIndex:number): void {
this.tableRowArray.removeAt(rowIndex);
}
/**
* Initializes the Form & by default adds an empty row to the PRIMENG TABLE
*/
private createForm(): void {
this.employeeForm = this.formBuilder.group({
tableRowArray: this.formBuilder.array([
this.createTableRow()
])
});
}
/**
* Returns the FormGroup as a Table Row
*/
private createTableRow(): FormGroup {
return this.formBuilder.group({
name: new FormControl(null, { validators: [Validators.required, Validators.minLength(3), Validators.maxLength(50)] })
});
}
}
Upvotes: 2
Views: 3383
Reputation: 1
To address the issue where all rows turn into edit mode when only one row is being edited, you need to ensure that each row in the table has a unique identifier that the dataKey can use to distinguish between them. Here’s how you can modify your code to include a unique identifier:
Component.html
<div class="card">
<div class="card-header">
<h5>Reactive Forms with PrimeNg Table</h5>
</div>
<div class="card-body">
<form [formGroup]="employeeForm">
<p-table [value]="tableRowArray.controls" [responsive]="true" dataKey="value.id" editMode="row"
responsiveLayout="scroll"> <!-- here i choose 'id' attribute as the unique identifier ... if your unique identifier is 'xyz', write dataKey="value.xyz" -->
<ng-template pTemplate="header">
<tr>
<ng-container *ngFor="let col of columns">
<td>{{col}}</td>
</ng-container>
</tr>
</ng-template>
<ng-template pTemplate="body" let-rowData let-rowIndex="rowIndex" let-editing="editing">
<ng-container formArrayName="tableRowArray">
<tr [formGroupName]="rowIndex" [pEditableRow]="rowData">
<td style="text-align:center">
<button *ngIf="!editing" pButton pRipple type="button" pInitEditableRow icon="pi pi-pencil" class="p-button-rounded p-button-text"></button>
<button *ngIf="editing" pButton pRipple type="button" pSaveEditableRow icon="pi pi-check" class="p-button-rounded p-button-text p-button-success mr-2"></button>
<button *ngIf="editing" pButton pRipple type="button" pCancelEditableRow icon="pi pi-times" class="p-button-rounded p-button-text p-button-danger"></button>
</td>
<td>
<p-cellEditor>
<ng-template pTemplate="input"></ng-template>
<ng-template pTemplate="output">
<input type="text" class="form-control form-control-sm"
formControlName="name" />
<div class="text-danger"
*ngIf="rowData.get('name').errors && (rowData.get('name').dirty || rowData.get('name').touched)">
<div *ngIf="rowData.get('name').errors?.required">Name is Required</div>
</div>
</ng-template>
</p-cellEditor>
</td>
</tr>
</ng-container>
</ng-template>
</p-table>
</form>
</div>
<div class="card-footer">
<button type="button" class="btn btn-primary btn-sm pull-left" (click)="addNewRow()">Add Row</button>
<button type="button" class="btn btn-success btn-sm pull-right" title="Save">Save</button>
</div>
</div>
Component.ts
import { Component, OnInit } from '@angular/core';
import { FormGroup, FormBuilder, FormArray, FormControl, Validators } from '@angular/forms';
@Component({
selector: 'app-add-employee',
templateUrl: './add-employee.component.html'
})
export class AddEmployeeComponent implements OnInit {
employeeForm: FormGroup;
columns: string[];
id: number = 0;
constructor(private formBuilder: FormBuilder) {
this.columns = ["Edit", "Name"];
}
ngOnInit(): void {
this.createForm();
}
get tableRowArray(): FormArray {
debugger;
return this.employeeForm.get('tableRowArray') as FormArray;
}
addNewRow(): void {
this.tableRowArray.push(this.createTableRow());
}
onDeleteRow(rowIndex:number): void {
this.tableRowArray.removeAt(rowIndex);
}
/**
* Initializes the Form & by default adds an empty row to the PRIMENG TABLE
*/
private createForm(): void {
this.employeeForm = this.formBuilder.group({
tableRowArray: this.formBuilder.array([
id: [this.id++],
// add other form attributes...
])
});
}
Upvotes: 0
Reputation: 538
You have dataKey set twice in your p-table tag. Apart from that I think you should assign an ID to your row data so that you can use that as a dataKey. I think you will need it for saving your row data anyway.
Upvotes: 1