有条件地渲染取决于 p:selectOneMenu 值
Conditionally render depend on p:selectOneMenu value
我正在尝试从现有的 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>
这里有几个问题。
首先,
<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、请求、视图、会话和应用程序范围中查找名为 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">
以包装 仅 真正需要更新的组件。
我正在尝试从现有的 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>
这里有几个问题。
首先,
<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、请求、视图、会话和应用程序范围中查找名为 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">
以包装 仅 真正需要更新的组件。