Primefaces树动态上下文菜单

时间:2017-06-08 12:18:51

标签: primefaces jsf-2 tree contextmenu

我需要树的动态上下文菜单(基于某些权限在每个节点上不同,因此我不能为每个节点使用不同的菜单类型)。

我使用支持bean模型实现了它,并在每次选择更改时更新它。一切正常,但如果用户右键单击未选择的节点,则会发生以下情况:

    显示
  • 上下文菜单(以前选择的节点)
  • 上下文菜单已更新(由select事件触发),而不是再次隐藏
  • 再次右键单击显示更新的上下文菜单

我发现我的解决方法是treetable PEP-0008 ... e-of-tree /

但它不适用于树。

欢迎任何提示

PF 6.1.2,WF 10.0.0

1 个答案:

答案 0 :(得分:0)

我想我找到了一个有效的解决方案。我已经根据primeface的展示建立了一个例子

BasicView.java

package example;

import java.io.Serializable;
import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.ViewScoped;

import org.primefaces.context.RequestContext;
import org.primefaces.event.NodeSelectEvent;
import org.primefaces.model.DefaultTreeNode;
import org.primefaces.model.TreeNode;

@ManagedBean(name="treeBasicView")
@ViewScoped
public class BasicView implements Serializable {

    private TreeNode root;

    @ManagedProperty(value="#{selectionView}")
    SelectionView selectionView;

    @PostConstruct
    public void init() {
        root = new DefaultTreeNode("Root", null);
        TreeNode node0 = new DefaultTreeNode("Node 0", root);
        TreeNode node1 = new DefaultTreeNode("Node 1", root);

        TreeNode node00 = new DefaultTreeNode("Node 0.0", node0);
        TreeNode node01 = new DefaultTreeNode("Node 0.1", node0);

        TreeNode node10 = new DefaultTreeNode("Node 1.0", node1);

        node1.getChildren().add(new DefaultTreeNode("Node 1.1"));
        node00.getChildren().add(new DefaultTreeNode("Node 0.0.0"));
        node00.getChildren().add(new DefaultTreeNode("Node 0.0.1"));
        node01.getChildren().add(new DefaultTreeNode("Node 0.1.0"));
        node10.getChildren().add(new DefaultTreeNode("Node 1.0.0"));
        root.getChildren().add(new DefaultTreeNode("Node 2"));
    }

    public TreeNode getRoot() {
        return root;
    }

    public void onNodeSelect(NodeSelectEvent event){
        checkSelectionChanged();
    }

    public void onRightClickSelectListener(NodeSelectEvent e) {
            checkSelectionChanged();
        }

/* Update the contextMenu only if the selection has changed */
        private void checkSelectionChanged(){
            if(this.getSelectionView().getSelectedNode()!=this.getSelectionView().getPrevSelectedNode()){
            RequestContext.getCurrentInstance().update("treeform:mytreeContexMenu");
        }
    }

    public SelectionView getSelectionView(){
        return selectionView;
    }

    public void setSelectionView(SelectionView selectionView){
        this.selectionView=selectionView;
    }
}

MenuView.java

package example;

import javax.annotation.PostConstruct;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.RequestScoped;
import javax.faces.context.FacesContext;

import org.primefaces.model.menu.*;

@ManagedBean
@RequestScoped
public class MenuView {

    private MenuModel model;

    @ManagedProperty(value="#{selectionView}")
    SelectionView selectionView;


    public void init() {
        model = new DefaultMenuModel();

        //First submenu
        DefaultSubMenu firstSubmenu = new DefaultSubMenu("Dynamic Submenu");

        DefaultMenuItem item = new DefaultMenuItem("External");
        item.setUrl("http://www.primefaces.org");
        item.setIcon("ui-icon-home");
        firstSubmenu.addElement(item);

        model.addElement(firstSubmenu);

        //Second submenu
        DefaultSubMenu secondSubmenu = new DefaultSubMenu("Dynamic Actions");

        this.getTreeSelectionView().getSelectedNode();
        if(this.getTreeSelectionView().getSelectedNode()==null){
            return;
        }
        String nodeText = this.getTreeSelectionView().getSelectedNode().getData().toString();

        if(nodeText.contains("0")){ //just a condition
            item=new DefaultMenuItem("Action for 0");
            item.setIcon("ui-icon-disk");
            item.setCommand("#{menuView.save}");
            secondSubmenu.addElement(item);
        }

        if(nodeText.contains("1")){ //just a condition
            item=new DefaultMenuItem("Action for 1");
            item.setIcon("ui-icon-close");
            item.setCommand("#{menuView.delete}");
            item.setAjax(false);
            secondSubmenu.addElement(item);
        }

        if(nodeText.contains("2")){ //just a condition
            item=new DefaultMenuItem("Action for 2");
            item.setIcon("ui-icon-search");
            item.setCommand("#{menuView.redirect}");
            secondSubmenu.addElement(item);
        }

        model.addElement(secondSubmenu);
    }

    public MenuModel getModel() {
        if(model==null){
            this.init();
        }
        return model;
    }

    public void save() {}

    public void update() {}

    public void delete() {}


    public SelectionView getTreeSelectionView(){
        return selectionView;
    }

    public void setSelectionView(SelectionView selectionView){
        this.selectionView=selectionView;
    }
}

SelectionView.java

package example;

import java.io.Serializable;
import javax.annotation.PostConstruct;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.ViewScoped;
import javax.faces.context.FacesContext;
import org.primefaces.model.TreeNode;

@ManagedBean(name="selectionView")
@ViewScoped
public class SelectionView implements Serializable {


    private TreeNode selectedNode;
    private TreeNode prevSelectedNode;


    public TreeNode getSelectedNode() {
        return selectedNode;
    }

    public void setSelectedNode(TreeNode selectedNode) {
        this.setPrevSelectedNode(this.selectedNode);
        this.selectedNode = selectedNode;
    }

    public TreeNode getPrevSelectedNode(){
        return prevSelectedNode;
    }

    public void setPrevSelectedNode(TreeNode prevSelectedNode){
        this.prevSelectedNode=prevSelectedNode;
    }
}

tree.xhtml

<!DOCTYPE html>
        <html
                xmlns="http://www.w3.org/1999/xhtml"
                xmlns:ui="http://java.sun.com/jsf/facelets"
                xmlns:f="http://java.sun.com/jsf/core"
                xmlns:h="http://java.sun.com/jsf/html"
                xmlns:p="http://primefaces.org/ui">

        <h:head>
            <title><h:outputText value="Test tree"/></title>
            <h:outputScript library="scripts" name="navigator.js"/>

        </h:head>
        <h:body>

            <h:form id="treeform">

            <p:tree value="#{treeBasicView.root}" var="node" dynamic="true" id="mytree" selectionMode="single" selection="#{selectionView.selectedNode}">
                <p:ajax event="select" listener="#{treeBasicView.onNodeSelect}"/>
                <p:ajax event="contextMenu" listener="#{treeBasicView.onRightClickSelectListener}" oncomplete="PF('mytreeContexMenuVar').show()"/>

                <p:treeNode>
                    <h:outputText value="#{node}" />
                </p:treeNode>
            </p:tree>

            <p:contextMenu for="mytree" id="mytreeContexMenu" model="#{menuView.model}" widgetVar="mytreeContexMenuVar">

            </p:contextMenu>
            </h:form>
        </h:body>
</html>

mytree.js contextMenu应该更新,而不是显示 (基于此处的示例:https://dnhome.wordpress.com/2013/10/07

    var siteFunctions = {
        //patch to fix a problem that the context menu disappears after update
        //delay the show to occure after the update
        patchContextMenuShow: function() {
            'use strict';
            var protShow = PrimeFaces.widget.ContextMenu.prototype.show;
            siteFunctions.patchContextMenuShow.lastEvent = null;
            PrimeFaces.widget.ContextMenu.prototype.show = function(e) {
                var ret;
                if (e) {
                    siteFunctions.patchContextMenuShow.lastEvent = e;
                    siteFunctions.patchContextMenuShow.lastEventArg = arguments;

                     siteFunctions.patchContextMenuShow.lastEventContext = this;
                    //prevent default browser context menu
                     e.preventDefault();
                    e.stopPropagation();
                } else if (siteFunctions.patchContextMenuShow.lastEvent) {

                    ret = protShow.apply(siteFunctions.patchContextMenuShow.lastEventContext, siteFunctions.patchContextMenuShow.lastEventArg);
                    siteFunctions.patchContextMenuShow.lastEvent = null;
                }
                return ret;
            };
        }
    };

    $(document).ready(function() {
        'use strict';
        try {
            siteFunctions.patchContextMenuShow();
        } catch (e) {
            console.error(e);
        }
    });