【问题标题】:Clear JSF form input values after submitting提交后清除 JSF 表单输入值
【发布时间】:2011-10-21 23:45:58
【问题描述】:

如果有一个表单,并且有一个文本框和一个按钮,提交表单后如何擦除文本框的内容?

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

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

【问题讨论】:

  • 你可以使用javascript:document.getElementById("name").value = ""
  • 处理提交时不能将服务器端DataForm.Name的值设置为空字符串吗?这应该在提交后再次渲染视图时反映出来。

标签: forms jsf


【解决方案1】:

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

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

【讨论】:

    【解决方案2】:

    简介

    有几种方法可以实现这一点。天真的方法是简单地清空支持 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 方式摆弄导航案例,那么只需将 &lt;redirect/&gt; 添加到相关导航案例中即可。另见How to make redirect using navigation-rule

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

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

      无论哪种方式,如果您还查看了需要在请求 URL 中保留的参数,则将 &amp;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());
      }
      

      这只是一团糟,应该真正重构为一些实用程序类。

    请求/查看作用域 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 页面,在该页面上 F5 总是会触发一个新的新 GET 请求,那么在 action 方法中简单地清空模型字段应该不会造成太大伤害。

    另见:

    【讨论】:

    • 感谢这份很棒的详细指南!经过数小时的搜索,我终于明白了如何正确清除我正在努力清除的表格,并且也明白了正确的方法!谢谢
    【解决方案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】:

      您可以从表单提交时调用的 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;
      }
      

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

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

      【讨论】:

      • 感谢您的回答。欣赏它
      【解决方案5】:

      您可以在呈现响应时将不应重新绘制的托管 bean 的属性置空。这可以使用类似于下面发布的 sn-p 的代码来完成:

      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.submit) 之前,使用来自请求的值(即设置 DataForm.Name 的值)更新托管 bean 的内容。在呈现响应阶段呈现页面时,bean 的当前值用于将视图呈现给用户。除非在应用程序事件中更改了值,否则该值将始终是从请求中应用的值。

      【讨论】:

      • 有一个 integer 值我应该清除或设置为 0。当我采用上述方法时,它仍然给出我之前输入的值。
      • 也许你正在重置一个局部变量的值。只要您引用托管 bean 的属性,Integers 和 ints 都可以重置为 0。
      猜你喜欢
      • 2018-03-14
      • 2016-10-23
      • 1970-01-01
      • 2018-09-30
      • 1970-01-01
      • 2021-07-07
      • 1970-01-01
      • 2019-02-28
      相关资源
      最近更新 更多