1

我有一个包含许多列和行的 PrimeNG p 表,其中一列使用输入作为其单元格编辑器。精简版如下:

<p-table [value]="rowDatas" selectionMode="single" [(selection)]="selectedRowData">
<ng-template pTemplate="body" let-rowData let-rowIndex="rowIndex">
    <tr [pSelectableRow]="rowData">
        <td pEditableColumn>
            <p-cellEditor>
                <ng-template pTemplate="input">
                    <input id="{{'hours' + rowIndex}}" pInputText type="text" [(ngModel)]="rowData.hours">
                </ng-template>
                <ng-template pTemplate="output">
                    {{rowData.hours}}
                </ng-template>
            </p-cellEditor>
        </td>
</ng-template>

我可以使用 ViewChild 访问表格

@ViewChild(Table) private table: Table;

但我不知道从那里去哪里。PrimeNG 文档没有提示如何以编程方式触发单元格编辑。谷歌搜索它会用 EditableColumns 和 onClick 抛出一些东西,但这不起作用,并且会跳过应该编辑的行。

如果存在,我可以通过 ID 识别输入字段。但是只有在单元格处于编辑模式时才会添加实际的输入 HTML 标记。所以我不能使用标准的 getElementById.focus。

如何使用 PrimeNG p-table 开始编辑特定单元格?

4

3 回答 3

1

我有类似的问题,我找到了一个适用于我的解决方案:

模板:

 <p-table
      #docDataTable
      [value]="frameworkDocumentDataValues"

组件(Angular 8):

@ViewChild('docDataTable', {static: false}) private docDataTable: Table;

    ngAfterViewInit() {
        this.frameworkDocumentDataValues.forEach(row => this.docDataTable.initRowEdit(row));
      }

这种方法导致我们最初所有表格单元格都是可编辑的。我的目标是能够直接将值放入表格中,而无需点击编辑值、确认等按钮...

于 2020-11-17T17:47:58.733 回答
0

曾经我还必须做一种类似于网格的 Excel 和导航,我写了一个这样的指令:

  import {
    Directive,
    OnInit,
    ElementRef,
    NgZone,
    HostListener,
  } from "@angular/core";

  import { Table, EditableColumn } from "primeng/table";
  import { DomHandler } from "primeng/components/dom/domhandler";

  enum Direction {
    Up,
    Down,
  }

  @Directive({
    selector: "[ArrowNavigation]",
  })
  export class ArrowNavigationDirective extends EditableColumn implements OnInit {
    constructor(
      public dt: Table,
      public el: ElementRef,
      public domHandler: DomHandler,
      public zone: NgZone
    ) {
      super(dt, el, domHandler, zone);
    }

    ngOnInit() {
      this.el.nativeElement.tabIndex = 1;
    }

    @HostListener("keydown.ArrowLeft", ["$event"]) ArrowLeft(
      $event: KeyboardEvent
    ) {
      this.moveToPreviousCell($event);
    }

    @HostListener("keydown.ArrowRight", ["$event"]) ArrowRight(
      $event: KeyboardEvent
    ) {
      this.moveToNextCell($event);
    }

    @HostListener("keydown.ArrowUp", ["$event"]) ArrowUp($event: KeyboardEvent) {
      this.moveVertically($event, Direction.Up);
    }

    @HostListener("keydown.ArrowDown", ["$event"]) ArrowDown(
      $event: KeyboardEvent
    ) {
      this.moveVertically($event, Direction.Down);
    }

    private moveVertically($event: KeyboardEvent, direction: Direction) {
      const currentCell = this.findCell($event.target);
      let targetRow =
        direction === Direction.Up
          ? currentCell.parentElement.previousElementSibling
          : currentCell.parentElement.nextElementSibling;
      let targetCell = null;

      while (targetRow) {
        const editableColumns = this.domHandler.find(
          targetRow,
          ".ui-editable-column"
        );

        if (editableColumns.length > 0) {
          const targetColumnIndex = this.domHandler.index(currentCell);

          targetCell = targetRow.firstElementChild;
          for (let index = 0; index < targetColumnIndex; index++) {
            targetCell = targetCell.nextElementSibling;
          }

          targetRow = undefined;
        } else {
          targetRow =
            direction === Direction.Up
              ? targetRow.previousElementSibling
              : targetRow.nextElementSibling;
        }
      }

      if (targetCell) {
        this.domHandler.invokeElementMethod(targetCell, "click");
        $event.preventDefault();
      }
    }
  }

PrimeNG是提供左右移动但不上下移动的功能,所以必须编写该功能。

就像这样使用它:

  <td pEditableColumn ArrowNavigation>
      <p-cellEditor>
          <ng-template pTemplate="input">
              <input type="text" [(ngModel)]="myModel">
          </ng-template>
          <ng-template pTemplate="output">
              {{myModel]}}
          </ng-template>
      </p-cellEditor>
  </td>
于 2020-11-19T00:17:16.627 回答
0

我刚刚遇到您的问题,因为我有类似的要求。我需要转到下一行并根据键盘快捷键将第一个单元格设置为可编辑(在此示例中说 shift+z)。最终用户在此表中输入了大量数据,因此“请不要单击鼠标来减慢该过程”是他们的要求之一。这就是我实现它的方式。

将 id 添加到表格单元格并将 keydown 事件添加到编辑器

<p-table [value]="rowDatas" selectionMode="single" [(selection)]="selectedRowData">
  <ng-template pTemplate="body" let-rowData let-rowIndex="rowIndex">
    <tr [pSelectableRow]="rowData">
     <td pEditableColumn id="hours{{rowIndex}}">
        <p-cellEditor>
            <ng-template pTemplate="input">
                <input id="{{'hours' + rowIndex}}" pInputText type="text" 
                [(ngModel)]="rowData.hours" (keydown.shift.z)="goNextRow($event,'hours', rowIndex)">
            </ng-template>
            <ng-template pTemplate="output">
                {{rowData.hours}}
            </ng-template>
        </p-cellEditor>
     </td>
    <td pEditableColumn id="minutes{{rowIndex}}">
        <p-cellEditor>
            <ng-template pTemplate="input">
                <input id="{{'minutes' + rowIndex}}" pInputText type="text" 
                [(ngModel)]="rowData.minutes" (keydown.shift.z)="goNextRow($event,'hours', rowIndex)">
            </ng-template>
            <ng-template pTemplate="output">
                {{rowData.minutes}}
            </ng-template>
        </p-cellEditor>
     </td>
     <td pEditableColumn id="seconds{{rowIndex}}">
        <p-cellEditor>
            <ng-template pTemplate="input">
                <input id="{{'seconds' + rowIndex}}" pInputText type="text" 
                [(ngModel)]="rowData.seconds" (keydown.shift.z)="goNextRow($event,'hours', rowIndex)">
            </ng-template>
            <ng-template pTemplate="output">
                {{rowData.seconds}}
            </ng-template>
        </p-cellEditor>
     </td>
  </ng-template>

脚本转到下一行。如果没有下一行,则转到第一行。

 goNextRow(event, columnName:string, index: number = 0) {
    event.stopPropagation(); 

    let element: HTMLElement = document.getElementById((columnName + (index + 1).toString())) as HTMLElement;
    if (element == undefined || element == null) {
        element = document.getElementById((columnName  + (0).toString())) as HTMLElement;
    }
    element.click();
}

然后通过 id 和 index 引用您要编辑的单元格。在这种情况下,无论我是在编辑小时、分钟还是秒,我都想转到下一行的小时列(第一列)。

  (keydown.shift.z)="goNextRow($event,'hours', rowIndex)"

但您可以将小时更改为任何其他单元格,即下一行的分钟列

(keydown.shift.z)="goNextRow($event,'minutes', rowIndex)"

基本上,它会触发表格单元格上的点击事件,使其可编辑。

于 2020-11-18T22:36:32.020 回答