I've been facing some problems using JSF with AJAX to render a table without reloading the whole page every time I submit a form.
我一直面临一些问题,使用JSF和AJAX来渲染表,而不是每次提交表单时都重新加载整个页面。
When I first run the server, my database is empty, so the page is supposed to show only a form to add books. When user submits the form, a fieldset
whith all books is supposed to be rendered. I don't want this fieldset
to be shown when database is empty.
当我第一次运行服务器时,我的数据库是空的,因此页面应该只显示一个表单来添加书籍。当用户提交表单时,应该呈现所有书籍的字段集。我不希望在数据库为空时显示此字段集。
This is a simple version of my code (it is just a small form and a table to be refreshed using AJAX):
这是我的代码的简单版本(它只是一个小表单和一个使用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>
And i wanna focus on this part:
我想专注于这一部分:
<h:commandButton value="Add book" action="#{livroBean.addFirstBook}">
<f:ajax execute="@form" render="title :addedBooksTable" />
</h:commandButton>
The fieldset and the table inside it are supposed to be hidden when there's no book added to the database, that's why i used <p:fieldset rendered="#{livroBean.numberOfBooks > 0}">
. But I want it to be rendered after I click the commandButton
, even if there's nothing at the inputText
.
当没有书添加到数据库时,应该隐藏字段集和其中的表,这就是我使用
Here's what's happening when I test the code:
这是我测试代码时发生的事情:
- if I test the code just as it is with an empty database, the
inputText
is refreshed (it "erases" what were typed before the submisssion) when I click on thecommandButton
, but the fieldset is not. I know that the fieldset has arendered="#{livroBean.numberOfBooks > 0}"
and the inputText does not, but the methodgetNumberOfBooks
is called everytime i click the commandButton, that's why I don't get it... - if I change the
f:ajax
tag so it ends up like this<f:ajax execute="@form" onevent="click" render="title :addedBooksTable" />
, it solves the problem, but i can realize the screen flashing for a while when I click thecommandButton
. As far as I know, one of the uses of AJAX is that we don't want the screen flashing when a request is made.
如果我像使用空数据库那样测试代码,那么当我点击commandButton时,inputText会被刷新(它“删除”在submisssion之前键入的内容),但是fieldset不是。我知道fieldset有一个render =“#{livroBean.numberOfBooks> 0}”而inputText没有,但每次点击commandButton时都会调用getNumberOfBooks方法,这就是为什么我没有得到它...
如果我更改了f:ajax标签,那么它最终会像这样
Why is the fieldset
rendered only when I use onevent="click"
? Should I consider the flashing something normal? Is there a more elegant solution for that?
为什么只有当我使用onevent =“click”时才会渲染字段集?我应该考虑闪烁的东西吗?有更优雅的解决方案吗?
Thanks!
1 个解决方案
#1
3
You can't ajax-update a plain HTML element. You can only ajax-update a JSF component. Simple reason is that the target must be resolveable by UIViewRoot#findComponent()
, so that JSF can find it in the component tree and render the updated HTML into the Ajax response.
您不能ajax更新纯HTML元素。您只能ajax更新JSF组件。简单的原因是UIViewRoot#findComponent()必须可以解析目标,以便JSF可以在组件树中找到它并将更新的HTML呈现到Ajax响应中。
Replace
<div id="addedBooksTable">
by
<h:panelGroup layout="block" id="addedBooksTable">
Normally, this should have thrown an exception as described in How to find out client ID of component for ajax update/render? Cannot find component with expression "foo" referenced from "bar", but they removed this check in Mojarra 2.2.5 in order to support ajax-updating a specific iteration of <ui:repeat>
and <h:dataTable>
(this missing check will be fixed later on as that's indeed unhelpful to starters like you).
通常,这应该抛出异常,如如何找出ajax更新/渲染的组件的客户端ID?找不到带有“bar”引用的表达式“foo”的组件,但是他们在Mojarra 2.2.5中删除了这个检查,以便支持ajax更新
As to why adding onevent="click"
appear to work, that's because it caused a JavaScript error which in turn caused the whole JavaScript/Ajax thing to break down, which in turn caused that the command button fall backs to default synchronous behavior with a full page reload (as if you aren't using <f:ajax>
at all). You likely meant to use event="click"
instead. The onevent
attribute serves a different purpose. See also a.o. Proccess onclick function after ajax call <f:ajax>.
至于为什么添加onevent =“click”似乎工作,那是因为它导致了JavaScript错误,这反过来又导致整个JavaScript / Ajax崩溃,从而导致命令按钮回退到默认的同步行为整页重新加载(就好像你根本没有使用
#1
3
You can't ajax-update a plain HTML element. You can only ajax-update a JSF component. Simple reason is that the target must be resolveable by UIViewRoot#findComponent()
, so that JSF can find it in the component tree and render the updated HTML into the Ajax response.
您不能ajax更新纯HTML元素。您只能ajax更新JSF组件。简单的原因是UIViewRoot#findComponent()必须可以解析目标,以便JSF可以在组件树中找到它并将更新的HTML呈现到Ajax响应中。
Replace
<div id="addedBooksTable">
by
<h:panelGroup layout="block" id="addedBooksTable">
Normally, this should have thrown an exception as described in How to find out client ID of component for ajax update/render? Cannot find component with expression "foo" referenced from "bar", but they removed this check in Mojarra 2.2.5 in order to support ajax-updating a specific iteration of <ui:repeat>
and <h:dataTable>
(this missing check will be fixed later on as that's indeed unhelpful to starters like you).
通常,这应该抛出异常,如如何找出ajax更新/渲染的组件的客户端ID?找不到带有“bar”引用的表达式“foo”的组件,但是他们在Mojarra 2.2.5中删除了这个检查,以便支持ajax更新
As to why adding onevent="click"
appear to work, that's because it caused a JavaScript error which in turn caused the whole JavaScript/Ajax thing to break down, which in turn caused that the command button fall backs to default synchronous behavior with a full page reload (as if you aren't using <f:ajax>
at all). You likely meant to use event="click"
instead. The onevent
attribute serves a different purpose. See also a.o. Proccess onclick function after ajax call <f:ajax>.
至于为什么添加onevent =“click”似乎工作,那是因为它导致了JavaScript错误,这反过来又导致整个JavaScript / Ajax崩溃,从而导致命令按钮回退到默认的同步行为整页重新加载(就好像你根本没有使用