Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use Primeng Menu with command and parameters in DataTable?

MenuItem of primeng has a parameter called command that is a function to be executed when its item is clicked. One example of using this is provided in https://www.primefaces.org/primeng/#/steps to give feedback to user.

command: (event: any) => {
                this.activeIndex = 0;
                this.msgs.length = 0;
                this.msgs.push({severity:'info', summary:'First Step', detail: event.item.label});
            }

However, I want to use the MenuItem as a column of my Primeng DataTable, like this.

enter image description here

And for this I need to use my menu this way:

<p-column>
  <ng-template let-item="rowData"
      <p-menu #menu popup="popup" [model]="items"></p-menu>
      <button type="button" pButton icon="fa fa-list" label="Show" (click)="menu.toggle($event)"></button>
  </ng-template>
</p-column>

To get "item" and the row that I'm clicking and other kind of data.

Using a buttom I can pass item and other data through onClick, but for this I need to create one column for each buttom. And to solve that I want to use Menu with MenuItem from primeng.

The problem is that I can't find any examples passing parameters through a command in MenuItem and I'm not find a way to do it.

How can I accomplish that using MenuItem with DataTable?

If that is not possible, how can I accomplish the same results?

like image 822
Gabriel Costa Avatar asked Nov 29 '17 19:11

Gabriel Costa


5 Answers

You can have a function that takes rowData and returns contextual MenuItem[]

<p-column>
  <ng-template let-item="rowData"
      <p-menu #menu popup="popup" [model]="getMenuItemsForItem(item)"></p-menu>
      <button type="button" pButton icon="fa fa-list" label="Show" (click)="menu.toggle($event)"></button>
  </ng-template>
</p-column>

  getMenuItemsForItem(item: MyItem): MenuItem[] {
    const context = item;
    return [
      { label: 'Label1', icon: 'fa-plus', command: e => this.takeAction(e, context) }
    ]
  }

UPDATE

[model]="getMenuItemsForItem(item)"

can cause performance issues, should be using a binding to an object instead.

[model]="menuItems[item.uniqueKey]"

and then set menuItems object with menu items for each item.

like image 72
sabithpocker Avatar answered Nov 20 '22 11:11

sabithpocker


I know this is old but one thing that could prevent having to have NN p-menu directives in your page would be to call a function from your component on button click instead of (click)="menu.toggle($event)" and in that function inject the data on each menu item.

I know this is kind of hacky but it's better than to replicate a p-menu for every table row.

Here is an example :

<p-menu #popupMenu [popup]="true" [model]="menuItems"></p-menu>

<!-- and where you want to open the menu -->
<a *ngIf="itemsMenu" (click)="toggleMenu(popupMenu, $event, rowData)">
    <i class="fas fa-chevron-circle-down"></i>
</a>
 toggleMenu(menu, event, rowData) {
    this.menuItems.forEach((menuItem) => {
      menuItem.data = rowData;
    });
    menu.toggle(event);
  }

Regards

like image 39
Mathieu de Lorimier Avatar answered Nov 20 '22 12:11

Mathieu de Lorimier


I found a way to solve the problem, although I think that it's not the best solution. I hope that those who are with the same problem can find it helpful.

Passing the table item via onClick and populating the menuItems with the callback works.

Sample:

Html

    <p-column>
      <ng-template let-item="rowData"
          <p-menu #menu popup="popup" (onClick)="onClickMenu(item)" [model]="items"></p-menu>
          <button type="button" pButton icon="fa fa-list" label="Show" (click)="menu.toggle($event)"></button>
      </ng-template>
    </p-column>

Typscript

    onClickMenu(item: any){

      this.items.push({label: 'Option 1',
                      command: (event: any) => {
                      doSomething(item);}
                      });

      this.items.push({label: 'Option 2',
                      command: (event: any) => {
                      doSomething(item);}
                      });

      this.items.push({label: 'Option 3',
                      command: (event: any) => {
                      doSomething(item);}
                      });
                    
    }
like image 31
Gabriel Costa Avatar answered Nov 20 '22 11:11

Gabriel Costa


JS

this.items = (rowData) => {
  return [
    {
      label: 'Certidão', icon: 'ui-icon-print', command: (event) => {
        console.log(rowData);
      }
    },
    {
      label: 'Declaração', icon: 'ui-icon-print', command: (event) => {
        console.log(rowData);
      }
    }
  ];
};

HTML

<p-splitButton label="{{ rowData.nomeColaborador }}" icon="ui-icon-folder" [model]="items(rowData)" >

If you want to pass a rowData you can explicit a function call like this

like image 1
Bryann Bueno Avatar answered Nov 20 '22 12:11

Bryann Bueno


Another option is to add the current menu rowData to a private variable upon menu selection like so:

<p-menu #menu popup="popup" [model]="items"></p-menu>
      <button type="button" class="btn-more" pButton icon="icon-more" label=" " (click)="menu.toggle($event);onClickMenu(rowData);"></button>

public onClickMenu(rowData: any) { 
        this.currentRowData = rowData; 
    }

Let me know if there are any repercussions in doing it this way, thanks.

like image 1
vicgoyso Avatar answered Nov 20 '22 11:11

vicgoyso