有条件地设置ui:param

时间:2013-12-04 10:10:45

标签: jsf-2 primefaces facelets

我想根据bean值设置一个ui:param,我想用c:if是个好主意。所以我在页面中输入了以下代码:

<ui:composition 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"
    xmlns:wai="http://www.id.ethz.ch/wai/jsf"
    template="/view/listView.xhtml">

        <c:if test="#{subscriptionListController.model.listViewName eq 'mySubscriptions'}">
         <ui:param name="title" value="#{msg.subscriptionTitleMySubscriptions}"/>
        </c:if>
        <c:if test="#{subscriptionListController.model.listViewName eq 'paidSubscriptions'}">
         <ui:param name="title" value="#{msg.subscriptionTitlePaidSubscriptions}"/>
        </c:if>
        <c:if test="#{subscriptionListController.model.listViewName eq 'allSubscriptions'}">
         <ui:param name="title" value="#{msg.subscriptionTitleAllSubscriptions}"/>
        </c:if>
        ....

但参数未设置...

如果我打印出#{subscriptionListController.model.listViewName eq 'mySubscriptions'}的值,我会在相应的情况下得到真,而在其他两种情况下则为假。

一开始我只有两种可能性并用三元运算符解决它:

<ui:param name="title" value="#{subscriptionListController.model.listViewName eq 'mySubscriptions' ? msg.subscriptionTitleMySubscriptions : msg.subscriptionTitlePaidSubscriptions}"/>

它有效。但现在我有更多的可能性......

我做错了什么?

2 个答案:

答案 0 :(得分:11)

<ui:composition template>所示,此页面代表模板客户端。

<ui:param>以外的任何<ui:define>适用于主模板(您在template属性中声明的文件),并在模板客户端本身内被忽略。如果您打算为模板客户端内部准备变量,则应将<ui:param>放在<ui:define>内。

但还有另一件事:<ui:param>的最初目的是将变量传递给<ui:composition template><ui:decorate template><ui:include src>引用的文件,而不是准备/设置变量在当前facelet上下文中。对于在当前EL上下文中准备/设置变量的唯一功能要求,您最好使用JSTL <c:set>来完成工作。您可以使用<ui:param>,但这不是它的原始意图,并且在较旧的MyFaces版本中无法正常工作。

因此,所以:

<ui:define>
    <c:if test="#{subscriptionListController.model.listViewName eq 'mySubscriptions'}">
        <c:set var="title" value="#{msg.subscriptionTitleMySubscriptions}"/>
    </c:if>
    <c:if test="#{subscriptionListController.model.listViewName eq 'paidSubscriptions'}">
        <c:set var="title" value="#{msg.subscriptionTitlePaidSubscriptions}"/>
    </c:if>
    <c:if test="#{subscriptionListController.model.listViewName eq 'allSubscriptions'}">
        <c:set var="title" value="#{msg.subscriptionTitleAllSubscriptions}"/>
    </c:if>
    ...
</ui:define>

对具体问题

无关,您可以按如下方式对其进行优化,而不需要一个只能在每个订阅类型中增长的不可维护的<c:if>组:

<ui:define>
    <c:set var="subscriptionTitleKey" value="subscriptionTitle.#{subscriptionListController.model.listViewName}">
    <c:set var="title" value="#{msg[subscriptionTitleKey]}"/>
    ...
</ui:define>

使用这些键

subscriptionTitle.mySubscriptions = Title for my subscriptions
subscriptionTitle.paidSubscriptions = Title for paid subscriptions
subscriptionTitle.allSubscriptions = Title for all subscriptions

答案 1 :(得分:2)

您正在使用JSTL与Facelets。 JSTL在视图构建期间执行,而不是在呈现阶段执行。此外,在JSF2库中处理它们存在一些问题 - 例如在较旧的Mojarra版本中,它们不适用于具有部分状态保存的视图范围bean - 请参阅https://stackoverflow.com/a/3343681)。这就是你的EL表达有效的原因。

解决方案是避免JSTL - 使用ui:repeat而不是c:forEach和EL表达式和条件渲染而不是c:if。