You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PrimeFaces menuItem中#{component}指向错误问题求助

问题背景

在JSF 2.2 + PrimeFaces 13.0.5环境下,实现菜单选中样式时,原写法需要手动传入viewId到styleClass的EL表达式中:

<p:menuitem value="My menu item" outcome="/some-view-id" 
    styleClass="#{currentView.isView('some-view-id') ? 'selected':''}" />

尝试通过#{component.outcome}自动获取当前菜单项的outcome以实现通用逻辑时,发现#{component}指向的是父组件<p:menu>而非当前<p:menuitem>,导致逻辑失效。使用binding属性虽可行,但需为每个菜单项单独声明绑定,无法达到通用目的。已知该问题在PrimeFaces 13.0.6中已修复,以下是当前版本的可行解决办法:

解决办法

办法一:在托管Bean中添加通用判断方法

在你的currentView托管Bean中新增一个无需传入参数的方法,通过JSF上下文获取当前正在渲染的菜单项组件,自动提取其outcome并判断是否为当前视图:

import javax.faces.context.FacesContext;
import javax.faces.component.UIComponent;
import org.primefaces.component.menuitem.MenuItem;

public boolean isCurrentMenuItemSelected() {
    FacesContext context = FacesContext.getCurrentInstance();
    UIComponent currentComponent = UIComponent.getCurrentComponent(context);
    
    // 确认当前组件是PrimeFaces菜单项
    if (currentComponent instanceof MenuItem) {
        MenuItem menuItem = (MenuItem) currentComponent;
        String outcome = menuItem.getOutcome();
        // 复用原有判断当前视图的逻辑
        return isView(outcome);
    }
    
    return false;
}

页面中直接调用该方法即可:

<p:menuitem value="My menu item" outcome="/some-view-id" 
    styleClass="#{currentView.currentMenuItemSelected ? 'selected':''}" />

办法二:封装复合组件复用逻辑

创建一个Facelets复合组件,将菜单项的选中样式逻辑封装在内,避免重复代码:

  1. 在WEB-INF/tags目录下创建menuItem.taglib.xml(若目录不存在则新建),内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<facelet-taglib xmlns="http://xmlns.jcp.org/xml/ns/javaee"
                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-facelettaglibrary_2_2.xsd"
                version="2.2">
    <namespace>http://example.com/jsf/custom</namespace>
    <tag>
        <tag-name>menuItem</tag-name>
        <source>/WEB-INF/components/menuItem.xhtml</source>
    </tag>
</facelet-taglib>
  1. 在WEB-INF/components目录下创建menuItem.xhtml复合组件文件:
<ui:component xmlns="http://www.w3.org/1999/xhtml"
              xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
              xmlns:p="http://primefaces.org/ui">
    <p:menuitem value="#{cc.attrs.value}" 
                outcome="#{cc.attrs.outcome}"
                styleClass="#{currentView.isView(cc.attrs.outcome) ? 'selected':''}" />
</ui:component>
  1. 在页面中引入自定义命名空间并使用复合组件:
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://xmlns.jcp.org/jsf/html"
      xmlns:p="http://primefaces.org/ui"
      xmlns:my="http://example.com/jsf/custom">

<!-- 使用自定义菜单项组件 -->
<my:menuItem value="My menu item" outcome="/some-view-id" />
</html>

办法三:直接升级PrimeFaces版本

若项目允许,直接升级到PrimeFaces 13.0.6及以上版本,该版本已修复#{component}指向错误的问题,可直接使用最初设想的通用写法:

<p:menuitem value="My menu item" outcome="/some-view-id" 
    styleClass="#{currentView.isView(component.outcome) ? 'selected':''}" />

内容的提问来源于stack exchange,提问作者Nikola

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 22:05:32