Ali
Ali

Reputation: 1678

PrimeNg context menu passing data issue

I am using PrimeNg's context menu v6.0.1, the problem is the documentation is not clear and I cannot find it over the web as well on how to pass data to command function e.g.:

I have 10 objects rendered on screen and context menu is attached to all of these objects, now if I click on menu item I want to get the id of the target object on which the context menu is rendered, how can this be accomplished?

<div id="block-container" *ngFor="let block of blocks">

    <!-- where to attach this block object ??? -->

    <p-contextMenu appendTo="body" 
      [target]="blockContextMenu" 
      [model]="contextMenuItems">
    </p-contextMenu>

    <div #blockContextMenu>
       Some implementation...
    </div>
</div>

and following is my items model:

this.contextMenuItems = [
  {
    label: 'Trip Details',
    command: (event) => {
      // event doesn't contain anything useful,
      // and only has the clicked menu item specific information.
  }}
];

Upvotes: 6

Views: 6236

Answers (5)

noamyg
noamyg

Reputation: 3104

You'll need to bind the a model to the context menu, just like in the documentation, but then programmatically change the model & open the menu.

1. Remove the target attribute from p-contextMenu - this would prevent out-of-the-box menu toggle mechanism.(<p-contextMenu #contextMenu appendTo="body" [model]="contextMenuItems"></p-contextMenu>)

2. Instead of referencing (<div #blockContextMenu></div>), use event binding (<div (contextmenu)="openContextMenu($event, dataYouNeedToPass)"></div>)

3. In your component, use @ViewChild to get access to the context menu and declare an empty model:

@ViewChild('contextMenu', { static: false }) contextMenu: ContextMenu;
contextMenuItems: MenuItem[] = [];

4. Add the openContextMenu function to programmatically change the model & open the context menu:

openContextMenu(event: MouseEvent, dataYouNeedToPass: any): void {
  this.contextMenuItems = [{
    label: 'Action One',
    command: (event) => this.doActionOne(dataYouNeedToPass)
  },
  {
    label: 'Action Two',
    command: (event) => this.doActionTwo(dataYouNeedToPass)
  }];
  this.documentActionContextMenu.show(event);
  event.stopPropagation();
}

Upvotes: 1

MagicLuckyCat
MagicLuckyCat

Reputation: 344

As the "Id's" are unique you need only pass it with the command() function:

https://primeng-panelmenu-return-id.stackblitz.io

  items: MenuItem[];

  ngOnInit() {
    this.items = [
      { label: "Rename", id: "1", command: () => this.onClickMenuItem("1") },
      { label: "Delete", id: "2", command: () => this.onClickMenuItem("2") },
      { label: "Add", id: "3", command: () => this.onClickMenuItem("3") }
    ];
  }

  onClickMenuItem(id: string) {
    console.log(id);
  }

Upvotes: 0

Ravindra Vairagi
Ravindra Vairagi

Reputation: 1083

We can get data on the PrimeNG context Menu Item click by just pushing data to command property callback function.

Below example code is also an example of the dynamic context menu creation with the Nth level.

For Example -

[
  {
    "ID": 1,
    "TITLE": "parent1",
    "SUBMENU": [
      {
        "ID": 2,
        "SUBMENU": [
          {
            "ID": 3,
            "SUBMENU": [
              {
                "ID": 4,
                "TITLE": "Child 1"
              }
            ]
          },
          {
            "ID": 13,
            "SUBMENU": [
              {
                "ID": 5,
                "TITLE": "Child 3"
              }
            ]
          },
          {
            "ID": 6,
            "SUBMENU": [
              {
                "ID": 7,
                "SUBMENU": [
                  {
                    "ID": 8,
                    "TITLE": "Child 4"
                  }
                ]
              },
              {
                "ID": 9,
                "SUBMENU": [

                ]
              }
            ],

          },
          {
            "ID": 10,
            "SUBMENU": [
              {
                "SUBMENU": [

                ]
              }
            ]
          }
        ],

      }
    ],

  },
  {
    "ID": 11,
    "TITLE": "parent2",
    "SUBMENU": [
      {
        "ID": 12,
        "TITLE": "Child 4"
      }
    ],

  }
]

From the above JSON, I created the PrimeNG context menu Items.

createContextMenuRecursive(object: any[]): MenuItem[] {
    if (object) {
      let menuList: MenuItem[] = [];
      for (var i = 0; i < object.length; i++) {
        if (object[i].ITEMS && object[i].ITEMS.length > 0) {
          let returnedList = this.createContextMenuRecursive(object[i].ITEMS);
          menuList.push(this.createMenuItem(object[i], returnedList));
        }
        else {
          menuList.push(this.createMenuItem(object[i]));
        }
      }
      return menuList;
    }
  }

The below function is used to create the PrimeNG context menu Item, where parameter data: any represents the data we need to use in command function.

createMenuItem(data: any, menuItems: MenuItem[] = []): MenuItem {
    if (menuItems.length > 0) {
      return { label: data.TITLE, items: menuItems, command: (event) => this.docGridContextMenuItemClick(event, data) };
    }
    else {
      return { label: data.TITLE, command: (event) => this.docGridContextMenuItemClick(event, data) };
    }
  }

Context menu item click event handler where we use the data.

docGridContextMenuItemClick(event: any, data: any) {
    console.log(JSON.stringify(data));
  }

Upvotes: 0

Niran Manandhar
Niran Manandhar

Reputation: 1107

  @ViewChild('copyMenu') copyMenu: ContextMenu;
  
    onLinkRightClicked(content: string, e: any): void {

    if (this.copyMenu) {
      let model: MenuItem[] = [];
      model.push({ label: 'Action', command: (event) => this.doAction(content) });
      this.copyMenu.model = model;
      this.copyMenu.show(e);
    }
  }
  
  doAction(content){
    // here 
  }
<div #blockContextMenu (contextmenu)="onLinkRightClicked(content, $event)">
       Some implementation...
</div>

<p-contextMenu appendTo="body" #targetContextMenu>
</p-contextMenu>

Upvotes: 4

Hrishikesh Kale
Hrishikesh Kale

Reputation: 6568

For a proper implementation of context menu with primeng you need to add

[contextMenu]="cm"

in an element which you want to show, for example, you want context menu over your div you need to mention

<div id="block-container" *ngFor="let block of blocks" [contextMenu]="cm"></div>

also in the p-contextMenu element, you need to do mentioned the variable of context menu from your div like

hope this helps.

Upvotes: 0

Related Questions