本文介绍了动态ui:include和ui:fragment:呈现为false的组件仍在组件树中生成的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

限时删除!!

我认为我不得不使用非常旧的MyFaces 2.0.5版本,而EL的动态包含会导致很多问题,因此我将ui:fragment切换为静态包含

I am force to use a very old version of MyFaces 2.0.5 I think, and dynamic include with EL cause so much problem, so I switch to static include with 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是可以的.我可以解决这个问题,所以现在提交表单时,我遇到了这个异常

With this, it still complain about duplicate id because I use same id on couples of these source file. So it seems that even rendered should be false, it still make it to the component tree. However duplicate id is fine. I can fix that easy, so now when I submit form, I got this exception

 /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,因此出现错误.您知道如何解决此问题吗?

so as you can see from the exception, it ListBoxFilter is the object I want, so only include ListBoxFilter.xhtml, but is being accessed checkBoxFilters.xhtml hence the error. Any idea how to fix this issue please?

推荐答案

<ui:include>不从UIComponent扩展.这是一个标记处理程序.因此,它根本不支持rendered属性.在标记文档中也没有列出.

The <ui:include> doesn't extend from UIComponent. It's a tag handler. It does thus not support the rendered attribute at all. It's also nowhere listed in the tag documentation.

<ui:fragment>确实是UIComponent.因此,基本上,您最终会得到全部,这3个包含文件在视图构建期间包含在内,因此,这3个物理文件最终都落入JSF组件树中.只有通过<ui:fragment rendered>有条件呈现的HTML输出.您仍然最终会从其中包含重复的组件ID,因为它们最终都在JSF组件树中.

<ui:fragment> is indeed an UIComponent. So basically you end up with all those 3 include files being included during view build time and thus all 3 physically end up in JSF component tree. It's only the HTML output which is conditionally rendered via <ui:fragment rendered>. You still end up with duplicate component IDs from those includes because they all end up in JSF component tree.

您应该使用像<c:if>这样的标记处理程序而不是<ui:fragment>有条件地构建JSF组件树.

You should be using a taghandler like <c:if> instead of <ui:fragment> to conditionally build the JSF component tree.

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

So, theoretically, this should do for each of them:

<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>时,这有一些警告:

This has however some caveats when #{filtersPopup} is a view scoped bean and/or when you're using <f:viewParam>:

  1. 这至少需要Mojarra 2.1.18,否则JSF视图作用域的bean将无法还原.

  1. This requires minimum Mojarra 2.1.18, otherwise JSF view scoped beans will fail to restore.

标记处理程序在视图构建期间运行.因此,此后运行的诸如<f:viewParam>之类的东西将根本无法工作.您需要回退到通过ExternalContext手动获取HTTP请求参数.

Taghandlers run during view build time. So things which runs thereafter like <f:viewParam> won't work at all. You'd need to fall back to manually grabbing HTTP request parameters via ExternalContext.

另请参见:

09-07 01:33