使用JSF和AJAX渲染隐藏元素

时间:2015-06-12 11:54:33

标签: ajax jsf jsf-2.2

我每次提交表单时都会遇到一些使用JSF和AJAX渲染表而没有重新加载整个页面的问题。

当我第一次运行服务器时,我的数据库是空的,因此页面应该只显示一个表单来添加书籍。当用户提交表单时,应该呈现fieldset所有书籍。当数据库为空时,我不希望显示此fieldset

这是我的代码的简单版本(它只是一个小表单和一个使用AJAX刷新的表):

<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui">

<h:head />
<h:body>
<h:graphicImage library="img" name="caelum-logo.png"/>

<h:form>
    <p>Book Title:</p>
    <h:inputText id="title" value="#{livroBean.livro.titulo}" />
    <h:commandButton value="Add book" action="#{livroBean.addFirstBook}">
        <f:ajax execute="@form" render="title :addedBooksTable" />
    </h:commandButton>
</h:form>

<div id="addedBooksTable">
    <p:fieldset rendered="#{livroBean.numberOfBooks > 0}">
        <h:dataTable value="#{livroBean.allBooks}" var="book">
            <h:column>
                <h:outputText value="#{book.titulo}" />
            </h:column>
        </h:dataTable>
    </p:fieldset>
</div>

</h:body>
</html>

我想关注这一部分:

<h:commandButton value="Add book" action="#{livroBean.addFirstBook}">
    <f:ajax execute="@form" render="title :addedBooksTable" />
</h:commandButton>

当数据库中没有添加任何书籍时,应该隐藏字段集及其中的表格,这就是我使用<p:fieldset rendered="#{livroBean.numberOfBooks > 0}">的原因。但是我希望在点击commandButton后进行渲染,即使inputText没有任何内容。

以下是我测试代码时发生的事情:

  • 如果我像使用空数据库那样测试代码,那么当我点击{{1}时,inputText会被刷新(它会删除#34;在调解之前键入的内容)但是,fieldset不是。我知道fieldset有一个commandButton而inputText没有,但每次点击commandButton都会调用方法rendered="#{livroBean.numberOfBooks > 0}",这就是为什么我没有得到它。
  • 如果我更改getNumberOfBooks标记,使其最终像f:ajax一样,则可以解决问题,但是当我点击<f:ajax execute="@form" onevent="click" render="title :addedBooksTable" />时,我可以看到屏幕闪烁一段时间。据我所知,AJAX的一个用途是我们不希望在发出请求时屏幕闪烁。

为什么commandButton仅在我使用fieldset时呈现?我应该考虑闪烁的东西吗?对此有更优雅的解决方案吗?

谢谢!

1 个答案:

答案 0 :(得分:4)

您无法更新纯HTML元素。您只能ajax更新JSF组件。原因很简单,目标必须由UIViewRoot#findComponent()解析,以便JSF可以在组件树中找到它并将更新的HTML呈现给Ajax响应。

替换

<div id="addedBooksTable">

通过

<h:panelGroup layout="block" id="addedBooksTable">

通常,这应该抛出How to find out client ID of component for ajax update/render? Cannot find component with expression "foo" referenced from "bar"中描述的异常,但他们在Mojarra 2.2.5中删除了此检查,以支持ajax更新<ui:repeat>和{{1的特定迭代(这个丢失的支票将在稍后修复,因为这对你这样的初学者来说确实没有帮助。)

至于为什么添加<h:dataTable>似乎有效,因为它导致了JavaScript错误,从而导致整个JavaScript / Ajax崩溃,从而导致命令按钮掉落在完整页面重新加载时返回默认的同步行为(就好像您根本没有使用onevent="click"一样)。您可能打算使用<f:ajax>代替。 event="click"属性有不同的用途。另见a.o. Proccess onclick function after ajax call <f:ajax>