angularprimengprimeng-table

Primeng MenuItem with command not working


I have create a table component and I am adding a split button for each row and trying to call the function but not working

Here is the function I am using to create the menu items

getItems(rowData: any): MenuItem[] {
  const items: MenuItem[] = [
  {
      label: 'Edit', icon: 'pi pi-fw pi-check', command: () => this.update(rowData)
  },
  { label: 'Delete', icon: 'pi pi-fw pi-times' }];
    return items;
  }

  update(employee: any): void {
    this.isEditMode = true;
    this.addEmployee = true;
    this.employee = { ...employee };
}

Here is how I am calling this inside my component

<app-prime-table [data]="data" [columns]="columns" [customBodyTemplate]="customBodyTemplate"
                [globalFilters]="columns" [displayFilter]="true">
            </app-prime-table>
            <ng-template #customBodyTemplate let-rowData>

                <tr>
                    <td *ngFor="let col of columns">
                        <div *ngIf="col.type == 'button' && rowData.isActive">
                            <!-- <button pButton pRipple icon="pi pi-pencil" (click)="update(rowData)"
                                class="p-button-rounded p-button-primary mr-1"></button>
                            <button pButton pRipple icon="pi pi-trash" (click)="delete(rowData)"
                                class="p-button-rounded p-button-danger"></button> -->
                        <p-splitButton label="Actions" [model]="getItems(rowData)" appendTo="body">
                        </p-splitButton>
                        </div>
                        <div *ngIf="!col.type">{{rowData[col.field]}}</div>
                        <div *ngIf="col.type == 'date'">{{formatDate(rowData[col.field])}}</div>
                    </td>
                </tr>
            </ng-template>

I can see the items but couldn't perform any action on it

enter image description here


Solution

  • The problem is coming due to using a function to get the list of values for the dropdown, due to the use of a function, a new reference to items is always getting created due to change detection running. To solve this issue, simply initialize the dropdown items once, you will notice that we have an event property on the command function, which we can use to access the data and perform actions!

    We can use styleClass to introduce a class to style the menu

    We can use onDropdownClick to store the active row and use that to perform the menu actions!

    code

    import { Component, OnInit } from '@angular/core';
    import { Product } from '../../domain/product';
    import { ProductService } from '../../service/productservice';
    import { MenuItem } from 'primeng/api';
    
    @Component({
      selector: 'table-basic-demo',
      templateUrl: 'table-basic-demo.html',
    })
    export class TableBasicDemo implements OnInit {
      products!: Product[];
      items: MenuItem[];
      activeRow!: Product | null;
    
      constructor(private productService: ProductService) {}
    
      ngOnInit() {
        this.items = this.getItems();
        this.productService.getProductsMini().then((data) => {
          this.products = data;
        });
      }
    
      getItems(): MenuItem[] {
        const items: MenuItem[] = [
          {
            label: 'Edit',
            icon: 'pi pi-fw pi-check',
            command: (event: any) => {
              console.log(event);
              this.update(this.activeRow);
            },
            styleClass: 'red',
          },
          { label: 'Delete', icon: 'pi pi-fw pi-times', styleClass: 'blue' },
        ];
        return items;
      }
    
      update(employee: any): void {
        alert(JSON.stringify(employee));
      }
    }
    

    html

     <div class="card">
      <p-table [value]="products" [tableStyle]="{ 'min-width': '50rem' }">
        <ng-template pTemplate="header">
          <tr>
            <th>Actions</th>
            <th>Code</th>
            <th>Name</th>
            <th>Category</th>
            <th>Quantity</th>
          </tr>
        </ng-template>
        <ng-template pTemplate="body" let-product>
          <tr>
            <td>
              <p-splitButton
                (onDropdownClick)="activeRow = product"
                label="Actions"
                [model]="items"
                appendTo="body"
                data-id="product.code"
              >
              </p-splitButton>
            </td>
            <td>{{ product.code }}</td>
            <td>{{ product.name }}</td>
            <td>{{ product.category }}</td>
            <td>{{ product.quantity }}</td>
          </tr>
        </ng-template>
      </p-table>
    </div>
    

    Stackblitz Demo