在模态表单中使用 Spring Boot 和 thymeleaf 进行服务器端验证

Posted

技术标签:

【中文标题】在模态表单中使用 Spring Boot 和 thymeleaf 进行服务器端验证【英文标题】:Server-side validation using spring boot and thymeleaf inside modal form 【发布时间】:2019-06-14 11:25:07 【问题描述】:

我只是在学习 spring boot 和 thymeleaf,我知道的是在模态表单中进行验证,而不重定向它,只是在这一步混淆。

我的班级模型

public class Class 

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @NotEmpty
    @NotBlank
    private String className;

    public Class(@NotEmpty @NotBlank String className) 
        this.className = className;
    

Html Fronted 显示模态

<div class="modal fade" id="addModal" tabindex="-1" th:fragment="modal-add" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
                <div class="modal-dialog" role="document">
                    <div class="modal-content">
                        <div class="modal-header">
                            <h5 class="modal-title" id="exampleModalLabel">Add Clas-s-room</h5>
                            <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                                <span aria-hidden="true">&times;</span>
                            </button>
                        </div>
                        <form th:action="@/addclass" th:object="$class" method="post">
                        <div class="modal-body">
                            <div class="form-group">
                                <label for="className">Class Name</label>
                                <input type="text" class="form-control" id="className" th:field="*className" placeholder="Name of Class">
                                <div class="text text-danger" th:if="$#fields.hasErrors('className')" th:errors="*className">
                            </div>
                        </div>
                        <div class="modal-footer">
                            <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
                            <button type="submit" value="Save" class="btn btn-primary">Save</button>
                        </div>
                        </form>
                    </div>
                </div>
            </div>

类控制器

@PostMapping("/addclass")
    public String addClass(@Valid @ModelAttribute("class") Class kelas, BindingResult result) 
        if(result.hasErrors()) 
            //what to do here ? to show error validation without closing modal?

        else
            classService.addClass(kelas);
        
        return "redirect:/classlist";
    

【问题讨论】:

我不确定您是否可以按照自己的方式进行操作。但是您可以尝试使用ajax 返回您要渲染的视图的名称(没有redirect:,所有内容都将被保留。另外我强烈建议为您的班级提供另一个名称然后Class,就像某处它会让你失败,你会使用错误的课程。 【参考方案1】:

在 thymeleaf 中使用开放式模态进行表单验证有点棘手。这是我的解决方案:

在您的控制器函数中添加“RedirectAttributes atts”。 添加属性值为 true 的 hasErrors。

@PostMapping("/addclass")
public String addClass(@Valid @ModelAttribute("class") Class kelas, BindingResult result, RedirectAttributes atts) 
    if(result.hasErrors()) 
        atts.addAttribute("hasErrors", true);
        return "classlist";
    else
        classService.addClass(kelas);
    
    return "redirect:/classlist";

在您的 html 文件中,您使用 th:inline 和 th:if 添加条件 JS 代码。因此,如果任何字段有错误,JS-Code 将被执行。在 JS-Code 中你可以打开模态框。

<div class="modal fade" id="addModal" tabindex="-1" th:fragment="modal-add" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
           <script th:inline="javascript" th:if="$#fields.hasErrors('*')">$("#addModal").modal("show");</script>
            <div class="modal-dialog" role="document">
                <div class="modal-content">
                    <div class="modal-header">
                        <h5 class="modal-title" id="exampleModalLabel">Add Clas-s-room</h5>
                        <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                            <span aria-hidden="true">&times;</span>
                        </button>
                    </div>
                    <form th:action="@/addclass" th:object="$class" method="post">
                    <div class="modal-body">
                        <div class="form-group">
                            <label for="className">Class Name</label>
                            <input type="text" class="form-control" id="className" th:field="*className" placeholder="Name of Class">
                            <div class="text text-danger" th:if="$#fields.hasErrors('className')" th:errors="*className">
                        </div>
                    </div>
                    <div class="modal-footer">
                        <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
                        <button type="submit" value="Save" class="btn btn-primary">Save</button>
                    </div>
                    </form>
                </div>
            </div>
        </div>

【讨论】:

【参考方案2】:

不清楚您要达到的目标;所以这是基于您的代码的通用答案。如果有任何错误,只需附加错误并返回原始映射即可。它不会重定向到任何其他页面,并将在网页上显示错误。根据您的代码的示例代码是 -

@PostMapping("/addclass")
public String addClass(@ModelAttribute("class") @Valid Class kelas, BindingResult result) 
       if(result.hasErrors()) 
            return "addClass";    
        
        //else is not required here. If there are errors, it is returned before reaching here anyways.
        classService.addClass(kelas);
        return "redirect:/classlist";

你的 html 应该是这样的(只有错误部分)-

<div class="text text-danger" th:if="$#fields.hasErrors('className')" th:errors="*className">
      <p>Incorrect Class Name</p>
</div>

您还可以在模态类本身或 application.properties 或最终静态类中指定错误消息并将其与响应一起发送。

您是新手,其他几点 - 避免使用 name as Class 作为类名。这将在以后的某个时间和时间造成混淆,这不是一个好的做法。使用一些正确的类名,即这个 Modal 类应该代表什么。其次,我相信构造函数也不需要@NotEmpty@NotBlank

【讨论】:

那个结果会再次重定向到页面对吗?我想要实现的是保持模态和通过百里香显示的错误 @jadugdestian 它将一直存在,直到请求完成。你试过我建议的改变吗?如果您遇到任何问题,您可以粘贴屏幕截图来解释一下吗? @jadugdestian 除非您像第二个 return 语句那样专门重定向,否则模型和错误将可用。 是的,这意味着页面将重新加载,并且模式将关闭。 @jadugdestian 是的,如果您自己刷新页面,模型可能会消失。它是您要求的一部分吗?否则,一旦请求从服务器返回,您将收到模型和错误消息。【参考方案3】:

在方法 addClass 你必须返回视图的样子。

 if(result.hasErrors()) 
        return "login";
    

登录是显示登录页面的页面。在登录页面中,您必须处理如下错误:

<span th:if="$#fields.hasErrors('className')" th:errors="*className">Class name Error</span>

【讨论】:

以上是关于在模态表单中使用 Spring Boot 和 thymeleaf 进行服务器端验证的主要内容,如果未能解决你的问题,请参考以下文章

Spring Boot thymeleaf 错误请求 400 而不是显示用户错误

带有 Thymeleaf th:object 的 Spring Boot 使用具有现有值的对象而不覆盖它们

Spring Boot整合Thymeleaf

如何在 Spring Boot Thymeleaf 列表中使用 Bootstrap 模式?

在 Spring Boot App 中使用 Jquery 和 FormData 提交表单字段并上传 File 到 Spring MVC Controller

在 Spring Boot 应用程序中使用 @Valid 和 BindingResult 时的表单输入验证问题