java JSF 渲染:EL 语句的条件不正确
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12323058/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
JSF rendering: condition of EL statement incorrect
提问by Menno
I have got a problem with my JSF-rendering. A given condition in Expression Language will not be executed in the right way. E.g:
我的 JSF 渲染有问题。表达式语言中的给定条件不会以正确的方式执行。例如:
Example 1
示例 1
<f:param name="cat" value="#{product.category.uri}" rendered="#{product.category.parent.uri == null}" />
<f:param name="cat" value="#{product.category.parent.uri}" rendered="#{product.category.parent.uri != null}" />
Example 2
示例 2
<c:if test="#{product.category.parent.uri == null}">
<f:param name="cat" value="#{product.category.uri}" />
</c:if>
<c:if test="#{product.category.parent.uri != null}">
<f:param name="cat" value="#{product.category.parent.uri}" />
</c:if>
Problem
问题
In both examples, both my parameters will be added to my surrounding h:outputLink. I am not sure what other code to add, so if you guys need anything else in order to help me, I'll be happy to provide it.
在这两个示例中,我的两个参数都将添加到我周围的 h:outputLink 中。我不确定要添加什么其他代码,所以如果你们需要其他任何东西来帮助我,我很乐意提供。
Thanks in advance.
提前致谢。
Example 3 (on request)
示例 3(应要求提供)
<?xml version='1.0' encoding='UTF-8' ?>
<ui:composition template="./WEB-INF/templates/base.xhtml"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:c="http://java.sun.com/jsp/jstl/core">
<ui:define name="content">
<c:choose>
<c:when test="#{webshop.productlist.size() > 0}">
<div id="spacer">
<ui:repeat value="#{webshop.productlist}" var="product">
<div id="block">
<p>
<h:outputLink value="product.xhtml">
#{product.name}
<c:choose>
<c:when test="#{product.category.parent.uri == null}">
<f:param name="cat" value="#{product.category.uri}" rendered="" />
</c:when>
<c:otherwise>
<f:param name="cat" value="#{product.category.parent.uri}" />
</c:otherwise>
</c:choose>
<f:param name="product" value="#{product.uri}" />
</h:outputLink>
</p>
</div>
</ui:repeat>
</div>
</c:when>
<c:otherwise>
(...)
</c:otherwise>
</c:choose>
</ui:define>
</ui:composition>
I have cleaned up this example a bit, but the essence is there. I have replaced the first examples by a when/otherwise construction, whether my product.category.parent.uri is null or not, it will give me the first result in this case.
我已经清理了这个例子,但本质就在那里。我已经用 when/otherwise 构造替换了第一个示例,无论我的 product.category.parent.uri 是否为空,在这种情况下它都会给我第一个结果。
回答by BalusC
Your core problem is that you're completely confusing view build time tags and view render time tags.
您的核心问题是您完全混淆了视图构建时间标签和视图渲染时间标签。
The view build time is that moment when a XHTML file is to be converted to a JSF component tree as available by FacesContext#getViewRoot()
. The view render time is that moment when the JSF component tree is about to produce HTML code, as initiated by UIViewRoot#encodeAll()
.
视图构建时间是将 XHTML 文件转换为可用的 JSF 组件树的那一刻FacesContext#getViewRoot()
。视图渲染时间是 JSF 组件树即将生成 HTML 代码的那一刻,由UIViewRoot#encodeAll()
.
All JSTL <c:xxx>
tags and all JSF <ui:xxx>
tags which do nothave a rendered
attribute run during view build time. All JSF <ui:xxx>
tags which dohave a rendered
attribute and all JSF <h:xxx>
tags run during view render time. So, they don't run in sync as you'd expect from the coding.
所有的JSTL<c:xxx>
标签和所有JSF<ui:xxx>
里面做标签不具有rendered
在视图生成时属性运行。所有的JSF<ui:xxx>
标签来办有一个rendered
属性,所有的JSF<h:xxx>
视图渲染时间期间运行的标签。因此,它们不会像您对编码所期望的那样同步运行。
Coming back to your concrete problem, this is two-fold:
回到你的具体问题,这是两方面的:
The
<f:param>
does as being a tag handler not support therendered
attribute at all.The
#{product}
is in your code definied by<ui:repeat var>
, which is a view render time tag, but yet you're trying to let JSTL<c:xxx>
view build time tags depend on that. This will of course not work. The#{product}
isnull
during the view build time, simply because the<ui:repeat>
hasn't run at that moment.
在
<f:param>
不为标记处理程序不支持rendered
的所有属性。该
#{product}
是你的代码由definied<ui:repeat var>
,这是一个视图渲染时间标记,但尚未你试图让JSTL<c:xxx>
视图生成时间标签依赖于这一点。这当然行不通。这#{product}
是null
在视图构建期间,仅仅是因为当时<ui:repeat>
还没有运行。
Your concrete problem can only be solved by using the view build time tag <c:forEach>
instead of the view render time tag <ui:repeat>
to iterate over products.
您的具体问题只能通过使用视图构建时间标签<c:forEach>
而不是视图渲染时间标签<ui:repeat>
来迭代产品来解决。
<c:forEach items="#{webshop.productlist}" var="product">
See also
也可以看看
Unrelatedto the concrete problem, the follwing clumsy block
与具体问题无关,下面的笨拙块
<c:choose>
<c:when test="#{product.category.parent.uri == null}">
<f:param name="cat" value="#{product.category.uri}" rendered="" />
</c:when>
<c:otherwise>
<f:param name="cat" value="#{product.category.parent.uri}" />
</c:otherwise>
</c:choose>
can be replaced by the following simpler approach with help of the conditional operator in EL:
在 EL 中的条件运算符的帮助下,可以用以下更简单的方法替换:
<f:param name="cat" value="#{empty product.category.parent.uri ? product.category.uri : product.category.parent.uri}" />
This way you must be able to keep using the <ui:repeat>
.
这样,您必须能够继续使用<ui:repeat>
.
回答by Bionic_Geek
According to the documentation, there is no rendered
attribute available for the f:param
tag so it is being ignored.
根据文档,标签没有rendered
可用的属性,f:param
因此它被忽略。
See for JSF <2.x - http://docs.oracle.com/javaee/5/javaserverfaces/1.2/docs/tlddocs/f/param.html
请参阅 JSF <2.x - http://docs.oracle.com/javaee/5/javaserverfaces/1.2/docs/tlddocs/f/param.html
See for JSF >2.0 - http://javaserverfaces.java.net/nonav/docs/2.0/pdldocs/facelets/f/param.html
请参阅 JSF > 2.0 - http://javaserverfaces.java.net/nonav/docs/2.0/pdldocs/facelets/f/param.html
Now that may suggest that example 2 should still work, so I might question whether or not product.category.parent.uri
is really null as opposed to empty (i.e. blank string). Have you tried to test for empty (checks for null and empty string)?
现在这可能表明示例 2 应该仍然有效,所以我可能会质疑是否product.category.parent.uri
真的为空而不是空(即空白字符串)。您是否尝试过测试是否为空(检查空字符串和空字符串)?
<c:if test="#{empty product.category.parent.uri}">
<f:param name="cat" value="#{product.category.uri}" />
</c:if>
<c:if test="#{!empty product.category.parent.uri}">
<f:param name="cat" value="#{product.category.parent.uri}" />
</c:if>
The other alternative, while not ideal, is to conditionally render two separate output links and determine which to render based on your value. Such as:
另一种选择虽然不理想,但有条件地呈现两个单独的输出链接,并根据您的值确定要呈现的内容。如:
<c:choose>
<c:when test="#{empty product.category.parent.uri}">
<h:outputLink value="product.xhtml">
<f:param name="cat" value="#{product.category.uri}"/>
<f:param name="product" value="#{product.uri}" />
</h:outputLink>
</c:when>
<c:otherwise>
<h:outputLink value="product.xhtml">
<f:param name="cat" value="#{product.category.parent.uri}" />
<f:param name="product" value="#{product.uri}" />
</h:outputLink>
</c:otherwise>
</c:choose>