PrimeFaces中如何仅为单个菜单项设置ajax=false?c:forEach内用c:if可行吗?
当然可行!
你完全可以在<c:forEach>内部用<c:if>来给特定的菜单项单独设置ajax="false",不过得先搞清楚JSTL标签和JSF组件的生命周期差异——JSTL标签是在视图构建阶段执行的,而JSF组件的rendered属性是在视图渲染阶段生效的,所以你的判断条件得确保在视图构建阶段就能拿到正确的值。
具体实现示例
假设你想给值为"Special Item"的菜单项关闭AJAX,代码可以这么写:
<p:menuButton id="Button" value="Select" > <c:forEach var="itemListVar" items="#{itemList}"> <!-- 对特定菜单项关闭AJAX --> <c:if test="#{itemListVar eq 'Special Item'}"> <p:menuitem id="#{itemListVar}" value="#{itemListVar}" actionListener="#{bean.processSelect}" process="@this" ajax="false" update="table:messages" rendered="true"> <f:attribute name="selectedRow" value="#{itemListVar}" /> </p:menuitem> </c:if> <!-- 其他菜单项保持AJAX开启 --> <c:if test="#{itemListVar ne 'Special Item'}"> <p:menuitem id="#{itemListVar}" value="#{itemListVar}" actionListener="#{bean.processSelect}" process="@this" ajax="true" update="table:messages" rendered="true"> <f:attribute name="selectedRow" value="#{itemListVar}" /> </p:menuitem> </c:if> </c:forEach> </p:menuButton>
更简洁的替代写法
其实不用写两个<c:if>,直接用EL表达式动态设置ajax属性就行,这样代码更简洁易维护:
<p:menuButton id="Button" value="Select" > <c:forEach var="itemListVar" items="#{itemList}"> <p:menuitem id="#{itemListVar}" value="#{itemListVar}" actionListener="#{bean.processSelect}" process="@this" <!-- 只有当不是特定项时才开启AJAX --> ajax="#{itemListVar ne 'Special Item'}" update="table:messages" rendered="true"> <f:attribute name="selectedRow" value="#{itemListVar}" /> </p:menuitem> </c:forEach> </p:menuButton>
这里ajax的取值会根据当前项动态判断:当itemListVar等于"Special Item"时,ajax是false,其他情况则为true,完美满足你的需求。
要注意的坑
- 视图构建阶段的取值时机:因为
<c:forEach>和<c:if>都是在视图构建阶段执行的,所以#{itemList}必须是在这个阶段就能访问到的——比如你得在@PostConstruct方法里初始化这个列表,而不是等到渲染阶段才加载。如果你的列表是依赖请求参数动态加载的,可能需要调整初始化时机,不过这种场景下<c:forEach>依然是合适的选择(毕竟<ui:repeat>是渲染阶段执行,没法用来创建组件实例)。 - ID唯一性:一定要保证每个
<p:menuitem>的id是唯一的,否则会触发JSF视图的重复ID异常,影响页面正常运行。
为什么这方法可行?
<c:forEach>会在视图构建阶段循环创建<p:menuitem>组件实例,不管是用<c:if>条件创建不同的组件,还是用EL动态设置ajax属性,都是在组件初始化阶段就确定了ajax的取值,完全符合JSF的组件生命周期规则,不会有冲突或失效的问题。
内容的提问来源于stack exchange,提问作者Tinkerbel
相关产品推荐
相关产品推荐

