推荐的方法来处理Thymeleaf Spring MVC AJAX Forms及其错误消息

时间:2015-08-25 05:44:45

标签: jquery ajax spring spring-mvc thymeleaf

在Thymeleaf方面处理AJAX表单及其错误消息的推荐方法是什么?

我目前有一个Spring控制器,它返回字段的JSON概述及其各自的错误消息,但不得不求助于使用完全手写的JQuery(或只是常规的Javascript)只是感觉有点不对,而且速度慢;特别是因为我打算在应用程序中使用大量的表单。

4 个答案:

答案 0 :(得分:20)

我喜欢做的是在发生错误时替换整个表单。以下是一个超级原始的例子。我不会使用大量的片段来渲染表格......只是保持简单。

这是用Spring 4.2.1和Thymeleaf 2.1.4编写的

表示用户信息表单的基本类:UserInfo.java

package myapp.forms;

import org.hibernate.validator.constraints.Email;
import javax.validation.constraints.Size;
import lombok.Data;

@Data
public class UserInfo {
  @Email
  private String email;
  @Size(min = 1, message = "First name cannot be blank")
  private String firstName;
}

控制器:UsersAjaxController.java

import myapp.forms.UserInfo;
import myapp.services.UserServices;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;

import javax.transaction.Transactional;

@Controller
@Transactional
@RequestMapping("/async/users")
public class UsersAjaxController {
  @Autowired
  private UserServices userServices;

  @RequestMapping(value = "/saveUserInfo", method = RequestMethod.POST)
  public String saveUserInfo(@Valid @ModelAttribute("userInfo") UserInfo userInfo,
                             BindingResult result,
                             Model model)  {
    // if any errors, re-render the user info edit form
    if (result.hasErrors()) {
        return "fragments/user :: info-form";
    }
    // let the service layer handle the saving of the validated form fields
    userServices.saveUserInfo(userInfo);
    return "fragments/user :: info-success";
  }
}

用于呈现表单和成功消息的文件:fragments / user.html

<div th:fragment="info-form" xmlns:th="http://www.thymeleaf.org" th:remove="tag">
  <form id="userInfo" name="userInfo" th:action="@{/async/users/saveUserInfo}" th:object="${userInfo}" method="post">
    <div th:classappend="${#fields.hasErrors('firstName')}?has-error">
      <label class="control-label">First Name</label>
      <input th:field="*{firstName}" type="text" />
    </div>
    <div th:classappend="${#fields.hasErrors('first')}?has-error">
      <label class="control-label">Email</label>
      <input th:field="*{email}" ftype="text" />
    </div>
    <input type="submit" value="Save" />
  </form>
</div>

<div th:fragment="info-success" xmlns:th="http://www.thymeleaf.org" th:remove="tag">
  <p>Form successfully submitted</p>
</div>

JS代码只是将表单提交到表单action属性中提供的URL。当响应返回到JS回调时,检查是否有任何错误。如果有错误,请将表单替换为响应中的表单。

(function($){
  var $form = $('#userInfo');
  $form.on('submit', function(e) {
    e.preventDefault();
    $.ajax({
      url: $form.attr('action'),
      type: 'post',
      data: $form.serialize(),
      success: function(response) {
        // if the response contains any errors, replace the form
        if ($(response).find('.has-error').length) {
          $form.replaceWith(response);
        } else {
          // in this case we can actually replace the form
          // with the response as well, unless we want to 
          // show the success message a different way
        }
      }
  });
})
}(jQuery));

同样,这只是一个基本的例子。正如上面的评论中所提到的,没有正确或错误的方法可以解决这个问题。这也不是我首选的解决方案,我肯定会对此做一些调整,但总的想法就在那里。

注意:我的JS代码中也有一个缺陷。如果将表单替换为响应中的表单,则表单提交处理程序将不会应用于新替换的表单。您需要确保在替换表单后正确地重新初始化表单处理程序,如果采用此路由。

答案 1 :(得分:0)

关于此的文档非常少,但如果您已熟悉Web Flow,则可能不需要更多。我不确定这种技术如何与Thymeleaf中的普通bean绑定一起使用。我很想看到一个完整的宠物诊所演示应用程序使用这个,所以我可以看到控制器。

docs

答案 2 :(得分:0)

不确定是否可以将其视为最佳做法,但这是我所做的:

Map<String, String> errorMap = binding.getFieldErrors()
   .stream().collect(Collectors.toMap(
        e -> e.getField(), e -> messageSource.getMessage(e, locale)));

然后,我将地图发送回给ajax响应,以在“成功”部分进行处理。

答案 3 :(得分:0)

不知道是否还有人感兴趣,但是为了任何寻求示例解决方案的人,我将其保留在这里。

我实现了yorgo的解决方案,并通过在片段中包含脚本来解决“缺陷”。还有一个小缺陷,即如果有多个带有额外参数的提交按钮(通常用于在spring + thymeleaf中实现动态表单),则在序列化表单时会丢失信息。我通过手动将此信息附加到序列化表单上来解决此问题。

您可以在以下位置查看我对yorgo解决方案的实施情况:https://github.com/Yepadee/spring-ajax/blob/master/src/main/resources/templates/project_form.html?fbclid=IwAR0kr_-t05_vFrPJxvbsG1Et7aLGir5ayXyPi2EKI6OHbEALgDfmHZ7HaKI

这样做的好处是,只需执行以下操作,就可以在任何现有的百里香形式上实现它:

  1. 将脚本放入表单,并使其引用表单的ID
  2. 将表格分成一个片段
  3. 在控制器中更改post方法以返回表单片段而不是整个模板