JSF:如何在ajax请求中刷新必填字段

4

好的,这里是核心问题。

这个页面有两个必填的“输入文本”。

一个命令按钮可以更改bean值并重新渲染“job”对象。

<a4j:form id="pervForm">  
    SURNAME:<h:inputText id="surname" label="Surname" value="#{prevManager.surname}" required="true" />  
    <br/>               
    JOB:<h:inputText  value="#{prevManager.job}"  id="job"  maxlength="10" size="10"  label="#{msg.common_label_job}" required="true" />  
    <br/>  

    <a4j:commandButton value="Set job to Programmer" ajaxSingle="true" reRender="job">  
        <a4j:actionparam name="jVal" value="Programmer" assignTo="#{prevManager.job}"/>  
    </a4j:commandButton>  

    <h:commandButton id="save" value="save"  action="save" class="HATSBUTTON"/>  

</a4j:form>  

这里是简单的管理器:
public class PrevManager   
{  

    private String surname;  
    private String job;  

    public String getSurname()  
    {  
        return surname;  
    }  

    public void setSurname(String surname)  
    {  
        this.surname = surname;  
    }  

    public String getJob()  
    {  
        return job;  
    }  

    public void setJob(String job)  
    {  
        this.job = job;  
    }  

    public String save()  
    {  
        //do something  
    }  

}  

让我们开始吧:

在“工作输入文本”中写入一些内容(例如“教师”)。 将姓留空。 保存。 出现验证错误(姓氏为必填项)。 按下“将职位设置为程序员”:没有任何反应。

检查bean值后,我发现它已经正确更新了,但页面上的组件没有更新!

根据我找到的JBoss文档,Ajax区域是一个关键的Ajax组件。当Ajax请求到来时,它限制要在服务器端处理的组件树部分。处理意味着在解码、验证和模型更新阶段进行调用。使用区域的最常见原因包括:

-避免在验证其他表单输入时中止JSF生命周期处理; -定义不同的事件传递策略(immediate="true/false"); -显示ajax状态的单独指示器; -提高渲染处理的性能(selfRendered="true/false",renderRegionOnly="true/false")

以下两个示例展示了验证错误不允许处理ajax输入的情况。键入名称。在第一个案例中,由于其他字段具有required="true"属性,此活动将被中止。您只会看到错误消息,而“工作”字段为空。

这是一个示例:

<ui:composition xmlns="http://www.w3.org/1999/xhtml"  
      xmlns:ui="http://java.sun.com/jsf/facelets"  
      xmlns:h="http://java.sun.com/jsf/html"  
      xmlns:f="http://java.sun.com/jsf/core"  
      xmlns:a4j="http://richfaces.org/a4j"  
      xmlns:rich="http://richfaces.org/rich">  

        <style>  
            .outergridvalidationcolumn {  
                padding: 0px 30px 10px 0px;  
            }  
        </style>  

    <a4j:outputPanel ajaxRendered="true">  
        <h:messages style="color:red" />  
    </a4j:outputPanel>  
    <h:panelGrid columns="2" columnClasses="outergridvalidationcolumn">  

        <h:form id="form1">  
                <h:panelGrid columns="2">  
                    <h:outputText value="Name" />  
                    <h:inputText value="#{userBean.name}">  
                        <a4j:support event="onkeyup" reRender="outname" />  
                    </h:inputText>  
                    <h:outputText value="Job" />  
                    <h:inputText  required="true" id="job2" value="#{userBean.job}" />  
                </h:panelGrid>  
        </h:form>  

        <h:form id="form2">  
            <h:panelGrid columns="2">  
                <h:outputText value="Name" />  
                <a4j:region>  
                    <h:inputText value="#{userBean.name}">  
                        <a4j:support event="onkeyup" reRender="outname" />  
                    </h:inputText>  
                </a4j:region>  
                <h:outputText value="Job" />  
                <h:inputText   required="true"  id="job1"  value="#{userBean.job}" />  
            </h:panelGrid>  
        </h:form>  

    </h:panelGrid>  
    <h:outputText id="outname" style="font-weight:bold" value="Typed Name: #{userBean.name}" />  
    <br />  
</ui:composition>  

表单1:行为不正确。我需要先填写工作,然后填写姓名。

表单2:行为正确。我不需要填写工作就能看到正确的值。

不幸的是,使用Ajax区域没有帮助(事实上我使用得很糟糕...),因为我的字段都是必填的。这是主要的不同之处。

有什么想法吗?

非常感谢。

3个回答

4
这个问题在JSF 2中也被发现,并在这个相关答案中详细解释:如何在PrimeFaces AJAX验证错误后填充文本字段? 总结一下,答案是当一个EditableValueHolder组件即将进行ajax渲染时,需要清除其状态,但它没有包含在ajax-execute中,可以通过调用方法setValue(null)setSubmittedValue(null)setLocalValueSet(false)setValid(true)来实现。注意:在JSF 2中,你可以使用方便的方法resetValue()来代替。
假设您的“工作”输入字段具有客户端ID prevForm:job,下面是如何在与“将工作设置为程序员”按钮相关联的操作监听器方法中清除它的方式:
UIInput input = (UIInput) context.getViewRoot().findComponent("prevForm:job");
input.setValue(null);
input.setSubmittedValue(null);
input.setLocalValueSet(false);
input.setValid(true);

0

当您单击“将工作设置为程序员”时,因为您没有重新渲染消息组件,所以什么也不会发生。如果这样做,您将能够看到验证消息。

您需要重新渲染消息,因为它是一个<a4j:commandButton/>,而不是一个简单的<h:commandButton/>

尝试在“将工作设置为程序员”按钮中使用prop.immediate并检查是否会更新字段。

<a4j:commandButton value="Set job to Programmer" ajaxSingle="true" reRender="job" immediate="true">
    <a4j:actionparam name="jVal" value="Programmer" assignTo="#{prevManager.job}"/>  
</a4j:commandButton>

我认为这里不必使用 "ajaxSingle"..

也许你可以尝试一个新的解决方案.. 使用 immediate,bean 值将不会被更新(也许!)。如果发生这种情况,则创建一个 bean 方法手动设置 bean 值。

否则,如果 bean 值已经更新并且字段仍为空,则尝试将 "job" 字段放入 <a4j:outputPanel/> 并重新渲染 outputPanel。

<a4j:outputPanel id="myPanel">
   <h:inputText  value="#{prevManager.job}"  id="job"  maxlength="10" size="10"  label="#{msg.common_label_job}" required="true" />
</a4j:outputPanel/>

<a4j:commandButton value="Set job to Programmer" reRender="myPanel" immediate="true">
    <a4j:actionparam name="jVal" value="Programmer" assignTo="#{prevManager.job}"/>  
</a4j:commandButton>

关于<a4j:outputPanel/>的更多信息在这里


我刚试过了。好的,immediate="true"不会像预期的那样更新bean。这可能是一个解决方案,但用户可能会迷失:提交后的验证错误将重置字段为先前的值。 - Tama
抱歉,如果我没有理解您的评论,但是immediate不会导致验证。这就是为什么我说,如果它不更新bean值,请创建一个bean方法来获取该值并手动设置到类中。有了这个,稍后在表单提交时,类将被加载,并且字段不会被重置,因为该字段将获取bean类的值(value =“#{prevManager.job}”)。 - Renan

0

使用a4j:actionparam将设置值,但在这种情况下无法帮助您绕过验证。验证发生在组件上(而不是bean属性)。因此,当您提交时,组件值仍为空。希望这可以帮到您。


我不在处理无效的组件。我只需要更改有效组件的值... 我更改了bean的值,但无法强制更新(immediate、reRender、ajaxRegion等都失败)。我找到的唯一方法是使用process属性。在这种情况下,组件会被正确更新,但仅当它具有初始值时才会如此(我的意思是:该组件具有非空值)。因此,没有办法强制... - Tama
将 ajaxSingle="true" 放在按钮上,然后重新渲染输入组件。 - Max Katz
我刚试了一下,但它不能正常工作。在我提交表格并触发页面上某个组件的验证错误之前,它都能正常工作。此时,按钮仅更新后台bean而不是页面上的字段。实际上,如果存在验证问题的组件是设计为通过ajax调用更新的组件,则它可以工作。但如果其他任何组件无效,则ajax按钮只能更新后台bean而不是组件。也许在提交后会发生阻止更新的事情。很抱歉,我有点慌了。 - Tama
我猜我不确定你想要实现什么。确保你了解JSF的生命周期,这篇文章也可能会有所帮助:http://mkblog.exadel.com/2009/07/richfaces-region-partial-jsf-tree-processing/ - Max Katz

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