在与反应式表单绑定的 PrimeNG 表中启用单行编辑会导致启用所有行编辑

问题描述 投票:0回答:2

我有一个可编辑的 PrimeNG 表,与反应式表单(而不是 ngtemplate)绑定。如果我单击单行的编辑,所有行都会变成编辑模式。这是解释我的问题的图片。

enter image description here

问题在于与 PrimeNg Edit 表一起使用的 dataKey。当使用反应式表单时,我不知道要与 dataKey 绑定什么。

这是解释问题的最小代码。

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>

组件.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)] })   
    });
  }

}
angular angular-reactive-forms primeng-datatable
2个回答
1
投票

您在 p-table 标签中设置了两次 dataKey。除此之外,我认为您应该为行数据分配一个 ID,以便您可以将其用作 dataKey。我认为无论如何你都需要它来保存行数据。


0
投票

为了解决只编辑一行时所有行都进入编辑模式的问题,需要确保表中的每一行都有一个唯一的标识符,dataKey可以使用该标识符来区分它们。以下是修改代码以包含唯一标识符的方法:

组件.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>

组件.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... 
      ])
    });
  }
© www.soinside.com 2019 - 2024. All rights reserved.