Render hidden elements using JSF and AJAX

时间:2022-01-19 20:03:07

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.

当没有书添加到数据库时,应该隐藏字段集和其中的表,这就是我使用

0}”>的原因。但是我希望在单击commandButton后呈现它,即使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 the commandButton, but the fieldset is not. I know that the fieldset has a rendered="#{livroBean.numberOfBooks > 0}" and the inputText does not, but the method getNumberOfBooks is called everytime i click the commandButton, that's why I don't get it...
  • 如果我像使用空数据库那样测试代码,那么当我点击commandButton时,inputText会被刷新(它“删除”在submisssion之前键入的内容),但是fieldset不是。我知道fieldset有一个render =“#{livroBean.numberOfBooks> 0}”而inputText没有,但每次点击commandButton时都会调用getNumberOfBooks方法,这就是为什么我没有得到它...

  • 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 the commandButton. 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.
  • 如果我更改了f:ajax标签,那么它最终会像这样 ,它解决了问题,但我可以实现屏幕单击commandButton时闪烁一会儿。据我所知,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崩溃,从而导致命令按钮回退到默认的同步行为整页重新加载(就好像你根本没有使用 )。您可能打算使用event =“click”。 onevent属性用于不同的目的。另见a.o.在ajax调用 之后获取onclick函数。

#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崩溃,从而导致命令按钮回退到默认的同步行为整页重新加载(就好像你根本没有使用 )。您可能打算使用event =“click”。 onevent属性用于不同的目的。另见a.o.在ajax调用 之后获取onclick函数。