Dynamic context menu on PrimeNG p-tree component

UI Components for Angular
Post Reply
efepege
Posts: 10
Joined: 02 Feb 2018, 18:16

19 Jan 2021, 14:52

I'm using PrimeNG UI library v10 in an Angular application. I have a `p-tree` component that show a list of items that must show a context menu when the user right-clicks on them. The problem is that each item will have different options, depending on its type. So, I'd need to run some logic to show/hide the appropriate context menu options before they're popped. This is the code:

Code: Select all

<p-tree [value]="treeItems" selectionMode="single" [(selection)]="selectedItem" [contextMenu]="treeContextMenu"></p-tree>

<p-contextMenu #treeContextMenu [model]="menuItems"></p-contextMenu>

I've tried binding the `contextMenu` property to a method that returns the `ContextMenu` reference and run the logic there, but it didn't work. Something like:

Code: Select all

<p-tree [value]="treeItems" selectionMode="single" [(selection)]="selectedItem" [contextMenu]="buildContextMenu()"></p-tree>

<p-contextMenu #treeContextMenu [model]="menuItems"></p-contextMenu>

// IN THE COMPONENT CODE:
@ViewChild('treeContextMenu') treeContextMenu: ContextMenu;

public buildContextMenu(): ContextMenu {
  // NOTE: getItemMenuOptions is a method that return the appropriate items to show for the selected item in the tree
  const menuItemsToShow = this.getItemMenuOptions();

  // Update the context menu items (so it'll be updated in the 'treeContextMenu' component)
  this.menuItems = menuItemsToShow;

  // Return the reference to the context menu
  return this.treeContextMenu;
}
The above code shows the context menu, but I can't click on any option (it does nothing). Another approach would be to add a `contextmenu` event listener to each of the tree items to show a custom context menu for each of them, but I don't like it, as there could be potentially hundreds of items, with its corresponding listeners. Any suggestion on a more optimal approach?

Thanks in advance,

signorcase
Posts: 2
Joined: 20 Jan 2021, 20:56

20 Jan 2021, 21:33

// IN THE HTML CODE
<p-tree [value]="treeItems" selectionMode="single" [(selection)]="selectedItem" [contextMenu]="buildContextMenu()"></p-tree>
<p-contextMenu #treeContextMenu [model]="menuItems"></p-contextMenu>

// IN THE COMPONENT CODE:
@ViewChild('treeContextMenu') treeContextMenu: ContextMenu;
public buildContextMenu(): ContextMenu {
const menuItemsToShow = this.getItemMenuOptions();
this.menuItems = menuItemsToShow;
return this.treeContextMenu;
}


getItemMenuOptions() : any {
if(this.selectedItem.label == undefined)
return;
if(this.selectedItem.label == "Documents"){ //It's the first item label on contextMenu
return this.menuItems; //it's a list called menuItems: MenuItem[];
}
else if(this.selectedItem.label == "Pictures"){ //It's an other label on contextMenu
return this.menuItems2; //it's a list called menuItems2: MenuItem[];
}
}

cmalpicag
Posts: 1
Joined: 12 Jan 2021, 19:16

12 May 2021, 17:19

Hello. I needed to do something like that but noticed that the method was executed countless times, with no call handling. My solution to generate a context menu in a p-table was by placing the code that generates the menu options in the onShow event of p-contextMenu. I believe it applies the same for a p-tree.

I consider for your case the solution would be as follows:

Code: Select all

<p-contextMenu #treeContextMenu [model]="menuItems" (onShow)="getItemMenuOptions()"></p-contextMenu>
Greetings!

vikalpaul8
Posts: 1
Joined: 13 May 2021, 14:38

13 May 2021, 15:04

Thanks for the clarification. vidmate download instasave

alirizaadiyahsi
Posts: 1
Joined: 06 Nov 2021, 19:27

06 Nov 2021, 19:34

Tree:

Code: Select all

<p-tree
    [value]="treeData"
    selectionMode="single"
    [(selection)]="selectedDocumentFolder"
    [contextMenu]="contextMenu"
    (onNodeContextMenuSelect)="onTreeContextMenuSelect($event, contextMenu)">
ContextMenu:

Code: Select all

<p-contextMenu #contextMenu [model]="contextMenuItems" appendTo="body" baseZIndex="99999"></p-contextMenu>
ts file:

Code: Select all

onTreeContextMenuSelect(event, contextMenu) {
        // event.node.data is tree node data that you can use is for your condition
        // in this example I have a prop that named 'isFile'
        if (event.node.data.isFile){ 
            this.contextMenuItems = [
                {
                    label: this.l('EditFile'),
                    icon: 'pi pi-pencil',
                    command: () => someMetod
                }
            ];
        }else {
            this.contextMenuItems = [
                {
                    label: this.l('EditFolder'),
                    icon: 'pi pi-pencil',
                    command: () => someOtherMethod
                }
            ];
        }
    }

Post Reply

Return to “PrimeNG”

  • Information
  • Who is online

    Users browsing this forum: No registered users and 10 guests