动态ui:包含ui:fragment:具有呈现false的组件仍然在组件树内部生成

时间:2013-07-30 12:03:56

标签: jsf jsf-2 myfaces

我强迫使用MyFaces 2.0.5的旧版本我认为,动态包含EL导致这么多问题,所以我切换到静态包含ui:fragment

<ui:fragment rendered="#{filtersPopup.filterFileName == 'checkBoxFilters'}">
    checkBoxFilters
    <ui:include src="/analytics/checkBoxFilters.xhtml" rendered="#{filtersPopup.filter != null}"/>
</ui:fragment>
<ui:fragment rendered="#{filtersPopup.filterFileName == 'DateRelativeFilter'}">
    DateRelativeFilter
    <ui:include src="/analytics/DateRelativeFilter.xhtml" rendered="#{filtersPopup.filter != null}"/>
</ui:fragment>
<ui:fragment rendered="#{filtersPopup.filterFileName == 'listboxFilter'}">
    listboxFilter
    <ui:include src="/analytics/listboxFilter.xhtml" rendered="#{filtersPopup.filter != null}"/>
</ui:fragment>

有了这个,它仍然抱怨重复的id,因为我在这些源文件的夫妇上使用相同的id。因此,即使rendered应该是false,它仍然可以进入组件树。但重复的ID很好。我可以轻松解决这个问题,所以现在当我提交表单时,我得到了这个例外

 /analytics/checkBoxFilters.xhtml at line 24 and column 118 value="#{filtersPopup.filter.groups}": Property 'groups' not found on type ListBoxFilter

从异常中可以看出,ListBoxFilter是我想要的对象,所以只包含ListBoxFilter.xhtml,但是被访问checkBoxFilters.xhtml因此出错。知道如何解决这个问题吗?

1 个答案:

答案 0 :(得分:10)

<ui:include>不会从UIComponent延伸。它是一个标签处理程序。因此它根本不支持rendered属性。它也没有列在the tag documentation中。

<ui:fragment>确实是UIComponent。所以基本上你最终会在视图构建时间内包含所有这3个包含文件,因此所有3个文件最终都在JSF组件树中。它只是通过<ui:fragment rendered>有条件地呈现的HTML输出。您仍然会从这些包含重复的组件ID,因为它们都以JSF组件树结束。

您应该使用<c:if>之类的标记处理程序而不是<ui:fragment>来有条件地构建JSF组件树。

因此,从理论上讲,这应该适用于每一个:

<c:if test="#{filtersPopup.filterFileName == 'checkBoxFilters'}">
    checkBoxFilters
    <c:if test="#{filtersPopup.filter != null}">
        <ui:include src="/analytics/checkBoxFilters.xhtml" />
    </c:if>
</c:if>

... etc

#{filtersPopup}是视图范围的bean和/或当您使用<f:viewParam>时,这有一些警告:

  1. 这需要最小的Mojarra 2.1.18,否则JSF视图范围的bean将无法恢复。

  2. Taghandlers在视图构建期间运行。因此,像<f:viewParam>这样的事情根本不起作用。您需要回退到通过ExternalContext手动抓取HTTP请求参数。

  3. 另见: