有条件地渲染取决于 p:selectOneMenu 值
Posted
技术标签:
【中文标题】有条件地渲染取决于 p:selectOneMenu 值【英文标题】:Conditionally render depend on p:selectOneMenu value 【发布时间】:2015-12-18 22:05:25 【问题描述】:我正在尝试从现有的 Primefaces 组件构建一个自定义组件,我需要一些帮助。我有一个 selectOneMenu,我希望它根据在菜单中选择的选项来呈现或不呈现(并禁用或启用)其他组件。这里的难点是我不能使用托管 Bean 来做到这一点(我有几个原因),我需要一个纯 xhtml 代码。
我尝试了一些 <c:choose>
和 <ui:parameter>
的东西来创建布尔值,但由于某种原因,我看不到它不起作用。你们可以看看我的代码,看看你有什么想法吗?可能是一些我想不出来的简单的东西,也可能是我还不知道的东西。
<h:body>
<h:form id="abc">
<ui:repeat var="pd" value="#produtoMB.produtos">
<h:panelGroup id="linha">
<c:choose>
<c:when test="#pd.marca == X1">
<c:set var="render" value="#true" />
</c:when>
<c:otherwise>
<c:set var="render" value="#false" />
</c:otherwise>
</c:choose>
<p:selectOneMenu value="#pd.marca">
<f:selectItem itemLabel="Select One" itemValue="" noSelectionOption="true"/>
<f:selectItem itemLabel="Xbox One" itemValue="X1" />
<f:selectItem itemLabel="PlayStation 4" itemValue="PS4" />
<f:selectItem itemLabel="Wii U" itemValue="WU" />
<p:ajax update="linha" />
</p:selectOneMenu>
<p:inputText value="#pd.aparelho" disabled="#render"/>
<h:outputText value="Microsoft" rendered="#render"/>
<p:commandButton value="X" />
</h:panelGroup>
<br />
</ui:repeat>
<br />
<p:commandButton actionListener="#produtoMB.botaoMais" value="+" update="abc"/>
<p:commandButton actionListener="#produtoMB.botaoMenos" value="-" update="abc"/>
</h:form>
【问题讨论】:
【参考方案1】:这里有几个问题。
首先,
<ui:repeat ...>
<c:choose>
...
</c:choose>
</ui:repeat>
JSTL 标记在视图构建期间运行。在所有 JSF 组件运行之前,它只执行一次。因此,与您对 XML 代码流的直观期望相反,当<ui:repeat>
组件运行和迭代时,它不会被执行。另见JSTL in JSF2 Facelets... makes sense?
第二,
<c:when test="#pd.marca == X1">
...
<f:selectItem ... itemValue="X1" />
itemValue="X1"
代表String
。 EL 表达式#X1
基本上分别在 facelet、request、view、session 和 application 范围内查找名为 X1
的变量,直到找到第一个非空值。为了在 EL 中表示 String
值,您需要像 #'X1'
这样用单引号引用它。所以,你应该改用#pd.marca == 'X1'
。尽管如此,由于第一点中提到的原因,这仍然行不通。另见Specify conditional rendering of element inside <ui:repeat>? The <c:if> does not seem to work。
但是,您可以使用 <c:set>
在 EL 范围内创建别名,只要您不设置其 scope
属性即可。另见Defining and reusing an EL variable in JSF page。
在删除 JSTL <c:choose>
并修复 EL 表达式 #X1
以表示真正的 String
文字 #'X1'
后,它应该如下所示:
<ui:repeat var="pd" value="#produtoMB.produtos">
<p:selectOneMenu value="#pd.marca">
<f:selectItem itemLabel="Select One" itemValue="#null" />
<f:selectItem itemLabel="Xbox One" itemValue="X1" />
<f:selectItem itemLabel="PlayStation 4" itemValue="PS4" />
<f:selectItem itemLabel="Wii U" itemValue="WU" />
<p:ajax update="linha" />
</p:selectOneMenu>
<h:panelGroup id="linha">
<c:set var="marcaIsX1" value="#pd.marca eq 'X1'" />
<p:inputText value="#pd.aparelho" disabled="#marcaIsX1" />
<h:outputText value="Microsoft" rendered="#marcaIsX1" />
</h:panelGroup>
<p:commandButton value="X" />
</ui:repeat>
请注意,我还删除了未使用的 noSelectionOption="true"
并移动了 <h:panelGroup id="linha">
以包装仅真正需要更新的组件。
【讨论】:
Balus,非常感谢您的回答。这确实是一个更有意义的解决方案(出于某种原因,我什至没有考虑在每个“禁用”和“渲染”属性中写入条件的想法。在得到你的答案之前,我注意到我在 EL 表达式中的错误, 但也谢谢你!我真的很希望<c:set var="x1selected" value="#pd.marca == 'X1'" />
而不使用整个<c:choose>
块。另见***.com/q/6434866以上是关于有条件地渲染取决于 p:selectOneMenu 值的主要内容,如果未能解决你的问题,请参考以下文章
根据 p:dataTable 的每一行中的另一个 p:selectOneMenu 填充 p:selectOneMenu
Primefaces valueChangeListener 或 <p:ajax 侦听器未触发 p:selectOneMenu [重复]