【问题标题】:JSF rendering: condition of EL statement incorrectJSF 渲染:EL 语句的条件不正确
【发布时间】:2012-09-01 15:06:44
【问题描述】:

我的 JSF 渲染有问题。表达式语言中的给定条件不会以正确的方式执行。 例如:

示例 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}" />

示例 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>

问题

在这两个示例中,我的两个参数都将添加到我周围的 h:outputLink。 我不确定要添加什么其他代码,所以如果你们需要其他任何东西来帮助我,我很乐意提供。

提前致谢。

示例 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>

我已经对这个示例进行了一些清理,但精髓就在那里。 我已经用 when/otherwise 构造替换了第一个示例,无论我的 product.category.parent.uri 是否为空,在这种情况下它都会给我第一个结果。

【问题讨论】:

  • 不,给定的 .uri 实际上是空的。
  • 其实你应该调试一下为什么产品不在范围内。
  • 为什么你的EL有“#”号?不应该是“$”吗?
  • 您可能正在做某事。 $ 语句将立即呈现,而 # 语句将在需要时呈现。鉴于我的产品实例正在 ui:repeat 中使用,$-statement 可能会解决问题。我会在测试后立即报告。
  • 示例 1 中带有 $ 注释的 EL 语句将导致相同的问题,即两个名为“cat”的参数。

标签: java jsf rendering el conditional-statements


【解决方案1】:

根据文档,rendered 没有可用于 f:param 标记的属性,因此它被忽略了。

查看 JSF http://docs.oracle.com/javaee/5/javaserverfaces/1.2/docs/tlddocs/f/param.html

查看 JSF >2.0 - http://javaserverfaces.java.net/nonav/docs/2.0/pdldocs/facelets/f/param.html

现在这可能表明示例 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>

另一种选择虽然不理想,但有条件地渲染两个单独的输出链接,并根据您的值确定要渲染的链接。如:

<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>

【讨论】:

  • 我应该补充一点,根据 2.0 文档,它看起来像有 'disabled' 属性,所以如果你使用 JSF 2.0 或更高版本,你也许可以用它来实现你的原始目标。目前我没有可用的沙盒来测试它,但我认为值得一提...
  • 我会尝试这两个建议!
  • 省力。两者都不能解决您的特定问题。 Bionic_Geek 本身根本不了解具体问题,只是猜测答案,甚至没有测试/实验用例本身。
  • 为什么?我同意您关于渲染时间问题的观点,但是将我们提供的两个答案合并在一起,对数据进行适当的循环,参数选择问题是相同的。即使使用 c:ForEach 标记,您仍然不会在 f:param 上具有渲染属性。值得一提的是,我放在那里的代码 sn-p 不包括其余的 facelets 标签,这使其超出了您所谈论的主要问题的范围。但我确实很欣赏你的 cmets 中不具建设性的火焰。
【解决方案2】:

您的核心问题是您完全混淆了视图构建时间标签和视图渲染时间标签。

视图构建时间是将 XHTML 文件转换为 FacesContext#getViewRoot() 可用的 JSF 组件树的时刻。视图渲染时间是 JSF 组件树即将生成 HTML 代码的时刻,由 UIViewRoot#encodeAll() 发起。

所有JSTL &lt;c:xxx&gt; 标记和所有JSF &lt;ui:xxx&gt; 标记 在视图构建期间运行rendered 属性。 的所有 JSF &lt;ui:xxx&gt; 标记都具有 rendered 属性,并且所有 JSF &lt;h:xxx&gt; 标记在视图渲染期间运行。因此,它们不会像您对编码所期望的那样同步运行。

回到你的具体问题,这有两个方面:

  1. &lt;f:param&gt; 作为标签处理程序根本不支持rendered 属性。

  2. #{product} 在您的代码中由 &lt;ui:repeat var&gt; 定义,这是一个视图渲染时间标记,但您试图让 JSTL &lt;c:xxx&gt; 查看构建时间标记依赖于此。这当然行不通。 #{product} 在视图构建期间是 null,仅仅是因为 &lt;ui:repeat&gt; 在那一刻还没有运行。

您的具体问题只能通过使用视图构建时间标签&lt;c:forEach&gt;而不是视图渲染时间标签&lt;ui:repeat&gt;来迭代产品来解决。

<c:forEach items="#{webshop.productlist}" var="product">

另见


与具体问题无关,以下笨拙的块

<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>

在 EL 中的条件运算符的帮助下,可以用以下更简单的方法替换:

<f:param name="cat" value="#{empty product.category.parent.uri ? product.category.uri : product.category.parent.uri}" />

这样你必须能够继续使用&lt;ui:repeat&gt;

【讨论】:

  • 当然,我最近刚刚对 JSF 生命周期进行了一些研究,但我却成功地犯了这样一个“愚蠢”的错误。 BalusC,再次感谢您的大力帮助!
  • @BalusC: 那么如果一些faclets(ui标签)和h标签属于视图渲染时间,那么composite和rich(richfaces)标签属于什么?
  • @BalusC 它必须是一个标签处理程序,它的行为方式。所以自定义标签总是运行视图构建时间?那么,您如何创建在视图渲染时间(也就是说,在视图构建时间之后)运行的自定义标签?
  • @feder:请不要将组件与标签处理程序混淆。
  • @BalusC 我不知道。所以这是两个答案之一。假设自定义标签属于标签处理程序:balusc.blogspot.ch/2011/09/…
猜你喜欢
  • 2019-12-10
  • 2012-11-28
  • 1970-01-01
  • 2012-05-07
  • 1970-01-01
  • 2015-06-01
  • 1970-01-01
  • 2014-01-17
相关资源
最近更新 更多