1
votes

Table PrimeNG: comment démarrer une modification de cellule?

J'ai une p-table PrimeNG avec un certain nombre de colonnes et de lignes, une colonne utilise une entrée comme éditeur de cellule. Version compacte ci-dessous:

@ViewChild(Table) private table: Table;

J'ai accès à la table en utilisant ViewChild

<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>

Mais je ne sais pas où aller à partir de là. La documentation PrimeNG ne donne aucune indication sur la façon de déclencher une modification de cellule par programme. Googler, c'est lancer quelque chose avec EditableColumns et onClick, mais cela ne fonctionne pas et ignore les lignes à modifier.

Je suis capable d'identifier le champ de saisie via un identifiant, s'il était présent. Mais la balise HTML d'entrée réelle n'est ajoutée que si la cellule est mise en mode d'édition. Je ne peux donc pas utiliser le standard getElementById.focus.

Comment puis-je commencer à modifier une cellule spécifique à l'aide de PrimeNG p-table?


3 commentaires

Le même problème - je ne trouve aucune information sur la façon de définir la table modifiable après le chargement


Je n'ai jamais trouvé de solution


OK j'ai trouvé une solution, donnez-moi 1 minute pour répondre à votre question :)


3 Réponses :


0
votes

J'ai eu un problème similaire et j'ai trouvé une solution qui fonctionne dans mon cas:

Modèle:

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

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

composant (angulaire 8):

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

Cette approche conduit à la situation que nous avons initialement toutes les cellules du tableau modifiables. C'était mon objectif de pouvoir mettre des valeurs directement dans une table sans pointer sur des boutons comme modifier la valeur, confirmer etc ...


0 commentaires

0
votes

Je viens de tomber sur votre problème car j'avais une exigence similaire. J'avais besoin d'aller à la ligne suivante et de définir la première cellule comme modifiable en fonction d'un raccourci clavier (disons shift + z pour cet exemple). L'utilisateur final entre beaucoup de données dans ce tableau, donc "aucun clic de souris pour ralentir le processus s'il vous plaît" était l'une de leurs demandes. C'est ainsi que je l'ai réalisé.

Ajoutez un identifiant à vos cellules de tableau et ajoutez l'événement keydown aux éditeurs

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

Script pour aller à la ligne suivante. Si aucune ligne suivante, passez à la première ligne.

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

Et puis référencez la cellule que vous souhaitez modifier par l'identifiant et l'index. Dans ce cas, je souhaite accéder à la colonne des heures (1ère colonne) de la ligne suivante, que je modifie les heures, les minutes ou les secondes.

 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();
}

mais vous pouvez remplacer les heures par n'importe quelle autre cellule, c'est-à-dire la colonne des minutes sur la ligne suivante

<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>

Fondamentalement, il déclenche l'événement de clic sur la cellule du tableau, ce qui le rend modifiable.


0 commentaires

0
votes

Une fois, j'ai également dû faire une sorte de grille de type Excel et pour la navigation, j'ai écrit une directive comme celle-ci:

  <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>

PrimeNG fournissait des fonctions pour se déplacer à gauche et à droite mais pas de haut en bas, il fallait donc écrire la fonction.

Et utilisez-le simplement comme ceci:

  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();
      }
    }
  }


0 commentaires