Primefaces-如何向菜单项动态添加上下文菜单

Primefaces-如何向菜单项动态添加上下文菜单,primefaces,menu,contextmenu,menuitem,Primefaces,Menu,Contextmenu,Menuitem,我想以编程方式创建带有MenuItems的p:menu(它可以工作),并且每个MenuItem都应该有p:contextMenu(它不能工作) ManagedBean: @ManagedBean(name="leftMenuView") @SessionScoped public class LeftMenuView { private MenuModel model; @PostConstruct public void init() { model

我想以编程方式创建带有MenuItems的p:menu(它可以工作),并且每个MenuItem都应该有p:contextMenu(它不能工作)

ManagedBean:

@ManagedBean(name="leftMenuView")
@SessionScoped
public class LeftMenuView {

    private MenuModel model;

    @PostConstruct
    public void init() {
        model = new DefaultMenuModel();   
        DefaultMenuItem item = new DefaultMenuItem("Redirect");
        item.setId("redirectMenuItem");
        model.addElement(item);

        ContextMenu ctxMenu = new ContextMenu();
        ctxMenu.setFor("redirectMenuItem");
        MenuModel ctxModel = new DefaultMenuModel();
        MenuItem ctxItem = new DefaultMenuItem("Remove from favorities");
        ctxModel.addElement(ctxItem);

        ctxMenu.setModel(ctxModel);

    }

(...)
}
视图:

它在整个菜单栏上显示上下文菜单。单击菜单项或只是菜单组件并不重要

当我将其更改为:

uiComponent = (UIComponent) rootView
            .findComponent(":leftForm:leftMenu:redirectMenuItem");
uiComponent.getChildren().add(ctxMenu);
我得到“java.lang.IllegalArgumentException:leftMenu”

换句话说,我想得到这种行为:

uiComponent = (UIComponent) rootView
            .findComponent("leftForm");
uiComponent.getChildren().add(ctxMenu);
<h:form>
    <p:menu id="menu_id">
        <p:menuitem id="gmail_id" value="Gmail"/>
        <p:menuitem id="hotmail_id" value="Hotmail" />
    </p:menu>
    <p:contextMenu for="gmail_id">
        <p:menuitem value="Save" />
        <p:menuitem value="Delete"/>
    </p:contextMenu>
</h:form>


但是以编程方式(从源代码)。

在PrimeFaces类BaseMenureUnderer,encodeEnd()中,您在后端设置的Id会再次被GenerateUniqueID(..)覆盖

我为此提出了一个问题

如果你愿意,就投票吧。这似乎是一个错误。 它仍然存在于PrimeFaces 5.3.5中

所以答案是,目前无法为菜单项设置ID

这是我目前设置ID的解决方法:

将其放在faces-config.xml中,以使用您自己的MenuRender

<render-kit>
<renderer>
  <component-family>org.primefaces.component</component-family>
  <renderer-type>org.primefaces.component.MenuRenderer</renderer-type>
  <renderer-class>de.yourPackage.CustomMenuRenderer</renderer-class>
</renderer>
</render-kit>

org.primefaces.component
org.primefaces.component.menurender
de.yourPackage.custommenurender
然后创建一个custommenurender类,如下所示,只做了一点更改,不覆盖ID:

public class CustomMenuRenderer extends CustomBaseMenuRenderer {
protected void encodeScript(FacesContext context, AbstractMenu abstractMenu) throws IOException {
    Menu menu = (Menu) abstractMenu;
    String clientId = menu.getClientId(context);

    WidgetBuilder wb = getWidgetBuilder(context);
    wb.initWithDomReady("PlainMenu", menu.resolveWidgetVar(), clientId)
            .attr("toggleable", menu.isToggleable(), false);

    if (menu.isOverlay()) {
        encodeOverlayConfig(context, menu, wb);
    }

    wb.finish();
}

protected void encodeMarkup(FacesContext context, AbstractMenu abstractMenu) throws IOException {
    ResponseWriter writer = context.getResponseWriter();
    Menu menu = (Menu) abstractMenu;
    String clientId = menu.getClientId(context);
    String style = menu.getStyle();
    String styleClass = menu.getStyleClass();
    String defaultStyleClass = menu.isOverlay() ? Menu.DYNAMIC_CONTAINER_CLASS : Menu.STATIC_CONTAINER_CLASS;
    if (menu.isToggleable()) {
        defaultStyleClass = defaultStyleClass + " " + Menu.TOGGLEABLE_MENU_CLASS;
    }
    styleClass = styleClass == null ? defaultStyleClass : defaultStyleClass + " " + styleClass;

    writer.startElement("div", menu);
    writer.writeAttribute("id", clientId, "id");
    writer.writeAttribute("class", styleClass, "styleClass");
    if (style != null) {
        writer.writeAttribute("style", style, "style");
    }
    writer.writeAttribute("role", "menu", null);

    encodeKeyboardTarget(context, menu);

    if (menu.getElementsCount() > 0) {
        writer.startElement("ul", null);
        writer.writeAttribute("class", Menu.LIST_CLASS, null);
        encodeElements(context, menu, menu.getElements());
        writer.endElement("ul");
    }

    writer.endElement("div");
}

protected void encodeElements(FacesContext context, Menu menu, List<MenuElement> elements) throws IOException {
    ResponseWriter writer = context.getResponseWriter();
    boolean toggleable = menu.isToggleable();

    for (MenuElement element : elements) {
        if (element.isRendered()) {
            if (element instanceof MenuItem) {
                MenuItem menuItem = (MenuItem) element;
                String containerStyle = menuItem.getContainerStyle();
                String containerStyleClass = menuItem.getContainerStyleClass();
                containerStyleClass = (containerStyleClass == null) ? Menu.MENUITEM_CLASS : Menu.MENUITEM_CLASS + " " + containerStyleClass;

                if (toggleable) {
                    UIComponent parent = ((UIComponent) menuItem).getParent();
                    containerStyleClass = (parent instanceof Submenu) ? containerStyleClass + " " + Menu.SUBMENU_CHILD_CLASS : containerStyleClass;
                }

                writer.startElement("li", null);
                writer.writeAttribute("class", containerStyleClass, null);
                writer.writeAttribute("role", "menuitem", null);
                if (containerStyle != null) {
                    writer.writeAttribute("style", containerStyle, null);
                }
                if (menuItem.getId() != null) {
                    writer.writeAttribute("id", menuItem.getId(), null);
                }
                encodeMenuItem(context, menu, menuItem);
                writer.endElement("li");
            }
            else if (element instanceof Submenu) {
                encodeSubmenu(context, menu, (Submenu) element);
            }
            else if (element instanceof Separator) {
                encodeSeparator(context, (Separator) element);
            }
        }
    }
}

@SuppressWarnings("unchecked")
protected void encodeSubmenu(FacesContext context, Menu menu, Submenu submenu) throws IOException {
    ResponseWriter writer = context.getResponseWriter();
    String label = submenu.getLabel();
    String icon = submenu.getIcon();
    String style = submenu.getStyle();
    String styleClass = submenu.getStyleClass();
    styleClass = styleClass == null ? Menu.SUBMENU_TITLE_CLASS : Menu.SUBMENU_TITLE_CLASS + " " + styleClass;
    boolean toggleable = menu.isToggleable();

    //title
    writer.startElement("li", null);
    if (toggleable) {
        writer.writeAttribute("id", submenu.getClientId(), null);
    }
    writer.writeAttribute("class", styleClass, null);
    if (style != null) {
        writer.writeAttribute("style", style, null);
    }

    if (menu.getId() != null) {
        writer.writeAttribute("id", menu.getId(), null);
    }

    writer.startElement("h3", null);

    if (menu.isToggleable()) {
        encodeIcon(context, label, Menu.EXPANDED_SUBMENU_HEADER_ICON_CLASS);
    }

    if (icon != null) {
        encodeIcon(context, label, "ui-submenu-icon ui-icon " + icon);
    }

    if (label != null) {
        writer.writeText(label, "value");
    }

    writer.endElement("h3");

    writer.endElement("li");

    encodeElements(context, menu, submenu.getElements());
}

protected void encodeIcon(FacesContext context, String label, String styleClass) throws IOException {
    ResponseWriter writer = context.getResponseWriter();

    writer.startElement("span", null);
    writer.writeAttribute("class", styleClass, null);
    writer.endElement("span");
}
public类custommenurender扩展了custombasemenurender{
受保护的void encodeScript(FacesContext上下文,AbstractMenu AbstractMenu)引发IOException{
菜单菜单=(菜单)抽象菜单;
字符串clientId=menu.getClientId(上下文);
WidgetBuilder wb=getWidgetBuilder(上下文);
wb.initWithDomReady(“PlainMenu”,menu.resolveWidgetVar(),clientId)
.attr(“可切换”,menu.isToggleable(),false);
if(menu.isOverlay()){
EncodeOverlyConfig(上下文、菜单、wb);
}
wb.finish();
}
受保护的void encodeMarkup(FacesContext上下文,AbstractMenu AbstractMenu)引发IOException{
ResponseWriter=context.getResponseWriter();
菜单菜单=(菜单)抽象菜单;
字符串clientId=menu.getClientId(上下文);
字符串样式=menu.getStyle();
String styleClass=menu.getStyleClass();
字符串defaultStyleClass=menu.isOverlay()?menu.DYNAMIC\u CONTAINER\u CLASS:menu.STATIC\u CONTAINER\u CLASS;
if(menu.isToggleable()){
defaultStyleClass=defaultStyleClass+“”+Menu.togleable\u Menu\u类;
}
styleClass=styleClass==null?defaultStyleClass:defaultStyleClass+“”+styleClass;
startElement(“div”,菜单);
writeAttribute(“id”,clientId,“id”);
writeAttribute(“class”,styleClass,styleClass”);
如果(样式!=null){
writeAttribute(“风格”,风格,风格”);
}
writeAttribute(“角色”、“菜单”,null);
编码键盘目标(上下文、菜单);
如果(menu.getElementsCount()>0){
startElement(“ul”,空);
writer.writeAttribute(“class”,Menu.LIST\u class,null);
编码元素(上下文、菜单、menu.getElements());
作者:恩德莱恩(“ul”);
}
作者:恩德莱恩(“div”);
}
受保护的元素(FacesContext上下文、菜单菜单、列表元素)引发IOException{
ResponseWriter=context.getResponseWriter();
boolean-toggleable=menu.istogleable();
for(菜单元素:元素){
if(element.isRendered()){
if(MenuItem的元素实例){
MenuItem MenuItem=(MenuItem)元素;
字符串containerStyle=menuItem.getContainerStyle();
字符串containerStyleClass=menuItem.getContainerStyleClass();
containerStyleClass=(containerStyleClass==null)?Menu.MENUITEM\u类:Menu.MENUITEM\u类+“”+containerStyleClass;
如果(可切换){
UIComponent父项=((UIComponent)menuItem.getParent();
containerStyleClass=(子菜单的父实例)?containerStyleClass+“”+菜单。子菜单\子菜单\子类:containerStyleClass;
}
作者:startElement(“li”,空);
writeAttribute(“类”,containerStyleClass,null);
writeAttribute(“角色”,“菜单项”,null);
if(containerStyle!=null){
writeAttribute(“样式”,容器样式,空);
}
如果(menuItem.getId()!=null){
writer.writeAttribute(“id”,menuItem.getId(),null);
}
encodeMenuItem(上下文、菜单、菜单项);
作者:恩德莱恩(“李”);
}
else if(子菜单的元素实例){
编码子菜单(上下文、菜单、(子菜单)元素);
}
else if(分隔符的元素实例){
编码分隔符(上下文,(分隔符)元素);
}
}
}
}
@抑制警告(“未选中”)
受保护的子菜单(FacesContext上下文、菜单菜单、子菜单)引发IOException{
ResponseWriter=context.getResponseWriter();
字符串标签=子菜单.getLabel();
字符串图标=子菜单.getIcon();
字符串样式=子菜单.getStyle();
String styleClass=子菜单。getStyleClass();
styleClass=styleClass==null?Menu.SUBMENU\u TITLE\u CLASS:Menu.SUBMENU\u TITLE\u CLASS+“”+styleClass;
boolean-toggleable=menu.istogleable();
//头衔
作者:startElement(“li”,空);
如果(可切换){
writeAttribute(“id”,子菜单.getClientId(),null);
}
writeAttribute(“class”,styleClass,null);
如果(样式!=null){
writer.writeAttribute(“style”,style,null);
}
if(menu.getId()!=null){
writeAttribute(“id”,menu.getId(),null);
}
startElement(“h3”,空);
if(menu.isToggleable()){
编码图标(上下文、标签、菜单、扩展的子菜单、标题、图标、类);
}
如果(图标
public class CustomMenuRenderer extends CustomBaseMenuRenderer {
protected void encodeScript(FacesContext context, AbstractMenu abstractMenu) throws IOException {
    Menu menu = (Menu) abstractMenu;
    String clientId = menu.getClientId(context);

    WidgetBuilder wb = getWidgetBuilder(context);
    wb.initWithDomReady("PlainMenu", menu.resolveWidgetVar(), clientId)
            .attr("toggleable", menu.isToggleable(), false);

    if (menu.isOverlay()) {
        encodeOverlayConfig(context, menu, wb);
    }

    wb.finish();
}

protected void encodeMarkup(FacesContext context, AbstractMenu abstractMenu) throws IOException {
    ResponseWriter writer = context.getResponseWriter();
    Menu menu = (Menu) abstractMenu;
    String clientId = menu.getClientId(context);
    String style = menu.getStyle();
    String styleClass = menu.getStyleClass();
    String defaultStyleClass = menu.isOverlay() ? Menu.DYNAMIC_CONTAINER_CLASS : Menu.STATIC_CONTAINER_CLASS;
    if (menu.isToggleable()) {
        defaultStyleClass = defaultStyleClass + " " + Menu.TOGGLEABLE_MENU_CLASS;
    }
    styleClass = styleClass == null ? defaultStyleClass : defaultStyleClass + " " + styleClass;

    writer.startElement("div", menu);
    writer.writeAttribute("id", clientId, "id");
    writer.writeAttribute("class", styleClass, "styleClass");
    if (style != null) {
        writer.writeAttribute("style", style, "style");
    }
    writer.writeAttribute("role", "menu", null);

    encodeKeyboardTarget(context, menu);

    if (menu.getElementsCount() > 0) {
        writer.startElement("ul", null);
        writer.writeAttribute("class", Menu.LIST_CLASS, null);
        encodeElements(context, menu, menu.getElements());
        writer.endElement("ul");
    }

    writer.endElement("div");
}

protected void encodeElements(FacesContext context, Menu menu, List<MenuElement> elements) throws IOException {
    ResponseWriter writer = context.getResponseWriter();
    boolean toggleable = menu.isToggleable();

    for (MenuElement element : elements) {
        if (element.isRendered()) {
            if (element instanceof MenuItem) {
                MenuItem menuItem = (MenuItem) element;
                String containerStyle = menuItem.getContainerStyle();
                String containerStyleClass = menuItem.getContainerStyleClass();
                containerStyleClass = (containerStyleClass == null) ? Menu.MENUITEM_CLASS : Menu.MENUITEM_CLASS + " " + containerStyleClass;

                if (toggleable) {
                    UIComponent parent = ((UIComponent) menuItem).getParent();
                    containerStyleClass = (parent instanceof Submenu) ? containerStyleClass + " " + Menu.SUBMENU_CHILD_CLASS : containerStyleClass;
                }

                writer.startElement("li", null);
                writer.writeAttribute("class", containerStyleClass, null);
                writer.writeAttribute("role", "menuitem", null);
                if (containerStyle != null) {
                    writer.writeAttribute("style", containerStyle, null);
                }
                if (menuItem.getId() != null) {
                    writer.writeAttribute("id", menuItem.getId(), null);
                }
                encodeMenuItem(context, menu, menuItem);
                writer.endElement("li");
            }
            else if (element instanceof Submenu) {
                encodeSubmenu(context, menu, (Submenu) element);
            }
            else if (element instanceof Separator) {
                encodeSeparator(context, (Separator) element);
            }
        }
    }
}

@SuppressWarnings("unchecked")
protected void encodeSubmenu(FacesContext context, Menu menu, Submenu submenu) throws IOException {
    ResponseWriter writer = context.getResponseWriter();
    String label = submenu.getLabel();
    String icon = submenu.getIcon();
    String style = submenu.getStyle();
    String styleClass = submenu.getStyleClass();
    styleClass = styleClass == null ? Menu.SUBMENU_TITLE_CLASS : Menu.SUBMENU_TITLE_CLASS + " " + styleClass;
    boolean toggleable = menu.isToggleable();

    //title
    writer.startElement("li", null);
    if (toggleable) {
        writer.writeAttribute("id", submenu.getClientId(), null);
    }
    writer.writeAttribute("class", styleClass, null);
    if (style != null) {
        writer.writeAttribute("style", style, null);
    }

    if (menu.getId() != null) {
        writer.writeAttribute("id", menu.getId(), null);
    }

    writer.startElement("h3", null);

    if (menu.isToggleable()) {
        encodeIcon(context, label, Menu.EXPANDED_SUBMENU_HEADER_ICON_CLASS);
    }

    if (icon != null) {
        encodeIcon(context, label, "ui-submenu-icon ui-icon " + icon);
    }

    if (label != null) {
        writer.writeText(label, "value");
    }

    writer.endElement("h3");

    writer.endElement("li");

    encodeElements(context, menu, submenu.getElements());
}

protected void encodeIcon(FacesContext context, String label, String styleClass) throws IOException {
    ResponseWriter writer = context.getResponseWriter();

    writer.startElement("span", null);
    writer.writeAttribute("class", styleClass, null);
    writer.endElement("span");
}
public class CustomBaseMenuRenderer extends BaseMenuRenderer {
@Override
protected void encodeMenuItem(FacesContext context, AbstractMenu menu, MenuItem menuitem) throws IOException {
    ResponseWriter writer = context.getResponseWriter();
    String title = menuitem.getTitle();
    String style = menuitem.getStyle();
    boolean disabled = menuitem.isDisabled();

    writer.startElement("a", null);
    writer.writeAttribute("tabindex", "-1", null);
    if (shouldRenderId(menuitem)) {
        writer.writeAttribute("id", menuitem.getClientId(), null);
    }
    if (title != null) {
        writer.writeAttribute("title", title, null);
    }

    String styleClass = this.getLinkStyleClass(menuitem);
    if (disabled) {
        styleClass = styleClass + " ui-state-disabled";
    }

    writer.writeAttribute("class", styleClass, null);

    if (style != null) {
        writer.writeAttribute("style", style, null);
    }

    if (disabled) {
        writer.writeAttribute("href", "#", null);
        writer.writeAttribute("onclick", "return false;", null);
    }
    else {
        setConfirmationScript(context, menuitem);
        String onclick = menuitem.getOnclick();

        //GET
        if (menuitem.getUrl() != null || menuitem.getOutcome() != null) {
            String targetURL = getTargetURL(context, (UIOutcomeTarget) menuitem);
            writer.writeAttribute("href", targetURL, null);

            if (menuitem.getTarget() != null) {
                writer.writeAttribute("target", menuitem.getTarget(), null);
            }
        }
        //POST
        else {
            writer.writeAttribute("href", "#", null);

            UIComponent form = ComponentTraversalUtils.closestForm(context, menu);
            if (form == null) {
                throw new FacesException("MenuItem must be inside a form element");
            }

            String command;
            if (menuitem.isDynamic()) {
                String menuClientId = menu.getClientId(context);
                Map<String, List<String>> params = menuitem.getParams();
                if (params == null) {
                    params = new LinkedHashMap<String, List<String>>();
                }
                List<String> idParams = new ArrayList<String>();
                idParams.add(menuitem.getId());
                params.put(menuClientId + "_menuid", idParams);

                command = menuitem.isAjax() ? buildAjaxRequest(context, menu, (AjaxSource) menuitem, form, params) : buildNonAjaxRequest(context, menu, form, menuClientId, params, true);
            }
            else {
                command = menuitem.isAjax() ? buildAjaxRequest(context, (AjaxSource) menuitem, form)
                        : buildNonAjaxRequest(context, ((UIComponent) menuitem), form, ((UIComponent) menuitem).getClientId(context), true);
            }

            onclick = (onclick == null) ? command : onclick + ";" + command;
        }

        if (onclick != null) {
            if (menuitem.requiresConfirmation()) {
                writer.writeAttribute("data-pfconfirmcommand", onclick, null);
                writer.writeAttribute("onclick", menuitem.getConfirmationScript(), "onclick");
            }
            else {
                writer.writeAttribute("onclick", onclick, null);
            }
        }
    }

    encodeMenuItemContent(context, menu, menuitem);

    writer.endElement("a");
}

@Override
protected boolean shouldRenderId(MenuElement element) {
    if (element instanceof UIComponent) {
        return shouldWriteId((UIComponent) element);
    }
        return false;
}

@Override
protected void encodeMarkup(FacesContext context, AbstractMenu abstractMenu) throws IOException {
    // TODO Auto-generated method stub

}

@Override
protected void encodeScript(FacesContext context, AbstractMenu abstractMenu) throws IOException {
    // TODO Auto-generated method stub

}
}
MenuModel model = new DefaultMenuModel();

DefaultSubMenu subMenu = new DefaultSubMenu("some submenu");
DefaultMenuItem menuItem = new DefaultMenuItem("some item");
subMenu.addElement(menuItem);

model.addElement(subMenu);

model.generateUniqueIds();
for (AuthTransactions subMenus : subTransactions){
    String subMenuName = getI18NString(subMenus.getLabelId(),locale);
    DefaultMenuItem item = new DefaultMenuItem(
        subMenuName == null ? subMenus.getTransactionCode()
        : subMenuName);
    item.setCommand("#{" + subMenus.getViewClassName()
        + defaultMethodName + "}");
    item.setParam("menuTransactionCode",
            subMenus.getTransactionCode());
    item.setOnclick("PF('statusDialog').show()");
    item.setTitle(subMenus.getTransactionCode());
    item.setIcon(subMenus.getIcon());

    userMenuModel.addElement(item);

    ContextMenu ctxMenu = new ContextMenu();
    ctxMenu.setFor("leftmenu:"+subMenus.getTransactionCode());
    DynamicMenuModel ctxModel = new DynamicMenuModel();
    DefaultMenuItem ctxItem = new DefaultMenuItem("Add/Remove"
      +subMenus.getTransactionCode() + " to favorites","ui-icon-star");
    ctxItem.setCommand("#{currentUserManager.toggleFavorite}");
    ctxItem.setParam("menuTransactionCode", subMenus.getTransactionCode());
    ctxItem.setAjax(true);
    ctxItem.setOnclick("PF('statusDialog').show()");
    ctxItem.setUpdate(":topBar");
    ctxModel.addElement(ctxItem);
    ctxMenu.setModel(ctxModel);
    contextMenuList.add(ctxMenu);
}
 <ps:menu id="sm_leftmenu" model="#{userMenuModel}" stateful="false" />
<c:if test="#{userMenuModel != null and userMenuModel.elements !=null and !empty userMenuModel.elements}">
    <ul id="leftmenu:sm_leftmenu" class="layout-menubar-container">
        <c:forEach var="item" items="#{userMenuModel.elements}">
            <li id="#{item.id}" role="menuitem">
            <h:commandLink value="#{item.value}" action="#{item.command}" title="#{item.title}" onclick="PF('statusDialog').show();" id="#{item.title}">
                <f:param name="menuTransactionCode" value="#{item.title}" />
                <i class="#{item.icon} yellow" style="float:left;padding-right:5px;"></i>
            </h:commandLink>
            </li>
        </c:forEach>
    </ul>
</c:if>
<h:panelGroup rendered="#{currentUserManager.contextMenuList != null and !empty currentUserManager.contextMenuList}">
    <h:dataTable value="#{currentUserManager.contextMenuList}" var="contextMenu">
        <h:column>
            <p:contextMenu binding="#{contextMenu}" model="#{contextMenu.model}" for="#{contextMenu.for}" styleClass="favCtx"/>
        </h:column>
    </h:dataTable>
 </h:panelGroup>