提交后清除JSF表单输入值

时间:2011-08-07 21:00:17

标签: forms jsf clear

如果有表单,并且有文本框和按钮,那么在提交表单后如何删除文本框的内容?

<h:inputText id="name" value="#{bean.name}" />          
<h:commandButton id="submit" value="Add Name" action="#{bean.submit}" />

在文本框中输入值并提交后,该值仍会显示在文本框中。我需要在提交后清除文本框的内容。我怎样才能做到这一点?

5 个答案:

答案 0 :(得分:12)

您可以删除在呈现响应时不应重新绘制的托管bean的属性。这可以使用类似于下面发布的代码段的代码完成:

private String name;

public String getName(){return name;}
public void setName(String name){this.name=name};

public String submit()
{
    //do some processing
    ...
    // blank out the value of the name property
    name = null;
    // send the user back to the same page.
    return null;
}

当前行为的原因可以在JSF运行时如何处理请求中找到。对视图的所有JSF请求都按照JSF standard request-response lifecyle进行处理。根据生命周期,在执行应用程序事件(DataForm.Name)之前,使用来自请求的值(即,设置DataForm.submit的值)更新托管bean内容。在渲染响应阶段呈现页面时,bean的当前值用于将视图呈现给用户。除非在应用程序事件中更改了值,否则该值将始终是从请求中应用的值。

答案 1 :(得分:11)

简介

有几种方法可以实现这一目标。天真的方法是简单地清空支持bean中的字段。疯狂的方法是获取JS / jQuery,以便在提交后甚至在页面加载期间执行该操作。这些方式只会引入不必要的代码并指出思考/设计问题。所有你想要的只是一个新的请求/页面/视图/ bean。就像你得到GET请求一样。

POST-重定向-GET

因此,最好的方法是在提交后发送重定向。您可能已经听说过它:POST-Redirect-GET。它会在POST请求(表单提交)之后为您提供全新的GET请求,完全按照您的意图。这样做的另一个好处是,当最终用户随后无意中按下F5并忽略浏览器警告时,不会重新提交先前提交的数据。

有几种方法可以在JSF中执行PRG。

  1. 使用faces-redirect=true查询字符串返回相同的视图。假设/page.xhtml,您可以在操作方法中执行此操作:

    public String submit() {
        // ...
    
        return "/page.xhtml?faces-redirect=true";
    }
    

    如果您仍然在使用JSF 1.x方式的导航案例,那么就可以将<redirect/>添加到相关的导航案例中。另请参阅How to make redirect using navigation-rule

  2. 为了使其更具可重用性,您可以通过编程方式获取视图ID:

    public String submit() {
        // ...
    
        UIViewRoot view = FacesContext.getCurrentInstance().getViewRoot();
        return view.getViewId() + "?faces-redirect=true";
    }
    

    无论哪种方式,如果您还查看了需要在请求网址中保留的参数,请将&includeViewParams=true附加到结果中。另请参阅Retaining GET request query string parameters on JSF form submit

  3. 如果你正在使用一些在JSF上下文之外运行的URL重写解决方案,那么你最好抓住当前的请求URL(带有查询字符串)并使用ExternalContext#redirect()重定向到那个

    public void submit() throws IOException {
        // ...
    
        ExternalContext ec = FacesContext.getCurrentInstance().getExternalContext();
        StringBuffer requestURL = ((HttpServletRequest) ec.getRequest()).getRequestURL();
        String queryString = ((HttpServletRequest) ec.getRequest()).getQueryString();
        ec.redirect((queryString == null) ? requestURL.toString() : requestURL.append('?').append(queryString).toString());
    }
    

    这只是一个混乱,应该真的被重构到某个实用程序类。

  4. 请求/查看范围内的bean

    请注意,这一切都可以很好地与请求或视图范围的bean结合使用。如果你有一个与表单绑定的会话范围bean,那么不会从头开始重新创建bean。那你就是另一个需要解决的问题。将其拆分为一个较小的会话范围,一个用于会话范围数据,另一个范围用于视图范围数据。另请参阅How to choose the right bean scope?

    面对消息

    如果您因成功操作而显示面部消息,则只需将其设为flash消息即可。另请参阅How to show faces message in the redirected page

    public String submit() {
        // ...
    
        FacesContext context = FacesContext.getCurrentInstance();
        context.addMessage(clientId, message);
        context.getExternalContext().getFlash().setKeepMessages(true);
        return "/page.xhtml?faces-redirect=true";
    }
    

    的Ajax

    只有当你碰巧有一个只有ajax的页面时,F5才会总是触发一个全新的GET请求,那么简单地将动作方法中的模型字段归零不应该伤害那么多。

    另见:

答案 2 :(得分:4)

您可以从提交表单时调用的Bean方法中清除表单;`

private String name;
    private String description;
    private BigDecimal price;

/*----------Properties ------------*/
/*-----Getter and Setter Methods---*/

public void save()throws SQLException{
String sql = "INSERT INTO tableName(name,description,price) VALUES (?,?,?)";
    Connection conn = ds.getConnection();
    try {

        PreparedStatement pstmt = conn.prepareStatement(sql);
        pstmt.setString(1, getName());
        pstmt.setString(2, getDescription());
        pstmt.setBigDecimal(3, getPrice());

        pstmt.executeUpdate();
    } catch (SQLException e) {
        e.getMessage();
        e.toString();
    }finally{
        conn.close();
        clear();
    }

}//End Save Method

public void clear(){
    setName(null);
    setDescription(null);
    setPrice(null);
}//end clear`

请注意,在save方法的所有操作完成后,将从save方法调用clear()方法。作为一个选项,只有在方法操作成功时才​​能执行清除...下面的方法放在ProductController类中......

    public String saveProduct(){
    try {
        product.save(); 
    } catch (SQLException e) {
        e.printStackTrace();
    }
    return null;
}

来自view / jsp的方法调用如下所示:

<h:commandButton value="Save" action="#{productController.saveProduct}"/>

答案 3 :(得分:3)

你可以用jQuery做到这一点。

我遇到了类似的问题。我需要清除弹出窗口窗口。

<rich:popupPanel id="newProjectDialog" autosized="true"
        header="Create new project">
        <h:form id="newProjectForm">
            <h:panelGrid columns="2">
                <h:outputText value="Project name:" />
                <h:inputText id="newProjectDialogProjectName"
                    value="#{userMain.newProject.projectName}"         required="true" />
                <h:outputText value="Project description:" />
                <h:inputText id="newProjectDialogProjectDescription"
                    value="#{userMain.newProject.projectDescription}"     required="true" />
            </h:panelGrid>
            <a4j:commandButton id="newProjectDialogSubmit" value="Submit"
                oncomplete="#{rich:component('newProjectDialog')}.hide();     return false;"
                render="projects" action="#{userMain.addNewProject}" />
            <a4j:commandButton id="newProjectDialogCancel" value="Cancel"
                onclick="#{rich:component('newProjectDialog')}.hide();     return false;" />
        </h:form>
        </rich:popupPanel>

jQuery代码:

$('#newProjectForm').children('input').on('click', function(){$('#newProjectForm').find('table').find('input').val('');});

答案 4 :(得分:1)

我添加了一个代码片段,如何在这里为JSF 2递归重置当前ViewRoot的所有值: Reset all fields in form

这适用于提交的表单,显示验证错误以及表单中新输入的值。