2

我的 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 是否为空,在这种情况下它都会给我第一个结果。

4

2 回答 2

10

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

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

所有没有属性的JSTL<c:xxx>标记和所有 JSF<ui:xxx>标记都在视图构建时运行。所有具有属性的 JSF 标记和所有 JSF标记在视图呈现期间运行。因此,它们不会像您对编码所期望的那样同步运行。rendered<ui:xxx>rendered<h:xxx>

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

  1. <f:param>作为一个标签处理程序根本不支持该属性rendered

  2. #{product}您的代码中由 定义<ui:repeat var>,这是一个视图呈现时间标记,但是您试图让 JSTL<c:xxx>视图构建时间标记依赖于它。这当然行不通。#{product}是在null视图构建期间,仅仅是因为当时<ui:repeat>还没有运行。

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

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

这样,您必须能够继续使用<ui:repeat>.

于 2012-09-07T19:35:03.037 回答
0

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

请参阅 JSF <2.x - 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>
于 2012-09-07T19:32:26.177 回答