当我想要使用ajax更新一个带有rendered="#{some}"的组件时,为什么需要将其嵌套在另一个组件中?

36

所以我找到了一些接近这个问题的答案,也找到了足够的解决方案。但是即便如此,我仍然很想了解其中的工作原理。下面举个例子:

我有一个名为.xhtml的facelet页面,它看起来像这样(缩短版)。

<h:form id="resultForm">

    <h:panelGroup class="search_form" layout="block">
        <h:inputText id="lastname" value="#{search.lastname}"/>
        <h:commandButton action="#{search.find}" value="Find">
            <f:ajax execute="lastname" render="resultDisplay"/>
        </h:commandButton>
    </h:panelGroup>

    <h:dataTable value="#{search.searchResults}" var="results" id="resultDisplay"
            rendered="#{!empty search.searchResults}">  
        <h:column>
            #{results.field}
        </h:column>
    </h:dataTable>

</h:form>

现在为了简洁起见,我不会贴出所有支持bean代码,但我大概有这样的东西:

public void find() {
    searchResults = setResults(true);
}

在搜索之后,searchResults 是一个 ArrayList<Objects>,它不为 null - 在多个测试中进行了检查(可能为null,但在我进行的测试中不是)。

现在。这个代码是不起作用的

但是,如果我将 dataTable 嵌套在另一个元素内,比如说 panelGroup,那么它就会起作用。

<h:panelGroup id="resultDisplay">
    <h:dataTable value="#{search.searchResults}" var="results"
        rendered="#{!empty search.searchResults}">  
        <h:column>
            #{results.field}
        </h:column>
    </h:dataTable>
</h:panelGroup>

现在,这些更改可以让一切正常运作。我可以接受这个...但我想我也想要一些理解。为什么我必须嵌套这些组件?我肯定漏掉了什么!

1个回答

68

Ajax更新是由客户端的JavaScript语言执行的。 JavaScript只能访问HTML DOM树。 如果JSF没有将任何组件呈现到HTML输出中,则在Ajax更新时,HTML DOM树中没有可以被JavaScript获取的内容。 JavaScript无法通过其ID获取所需的元素。

只有在另一个始终呈现在HTML输出中且因此始终存在于HTML DOM树中且始终可被JavaScript获取的组件中包装有条件地渲染的JSF组件,它才能正常工作。 在ajax渲染/更新期间引用该包装器组件。

另请参见:


1
太好了!那就是我需要的解释。我一直以为JavaScript使用id来更新DOM。感谢您的启示! - blo0p3r
也许这个答案可以被改进,包含一些可能会发生的错误,就像http://stackoverflow.com/questions/30307378/jsf-how-to-update-element-illegalargumentexception-resultdisplay中的那个。 - Kukeltje

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接