Thymeleaf + Spring Boot: Modaler Dialog mit Validierung Server-Side

capilano

Lt. Junior Grade
Registriert
Juli 2009
Beiträge
375
Guten Morgen zusammen,

derzeit versuche ich mich ein wenig in Spring Boot mit Thymeleaf. Soweit klappt alles mit Authentifizierung und Anlegen, Löschen, Editieren von persistierten Daten. Allerdings möchte ich gerne das Anlegen sowie Editieren von Daten in einem Modalen Dialog verpacken.

Die "Startseite" sieht wie folgt aus:
1634976384202.png

Über den "Add Course" Button öffnet sich dann ein Modaler-Dialog
1634976420785.png


Nun komme ich nicht weiter. Ich möchte gerne eine Überprüfung einfügen, die prüft, ob der Name bereits in der Datenbank vorhanden ist, wenn ja, dann soll im ModalenDialog eine entsprechende Fehlermeldung auftauchen. Aktuell habe ich das Problem, dass es beim Klick auf "Save" auf die "http://localhost:8080/addcourse#" weiterleitet.
Hat jemand sich damit auseinander gesetzt ob dies möglich ist? Ggf. eine Anleitung gefunden, welche es mir ermöglicht dies umzusetzen?
Bin sehr dankbar über die Unterstützung.


Orientiert hatte ich mich an folgende Artikel:
https://frontbackend.com/thymeleaf/spring-boot-bootstrap-thymeleaf-modal
https://stackoverflow.com/questions...g-spring-boot-and-thymeleaf-inside-modal-form (Nachtrag)


HTML:
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns:sec="https://www.thymeleaf.org/thymeleaf-extras-springsecurity5">
<head>
    <meta charset="utf-8">
    <title th:text="#{schoolbook.title}"></title>

    <link href="/css/main.css" rel="stylesheet">
    <link href="/css/font-awesome.css" rel="stylesheet">
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" integrity="sha384-JcKb8q3iqJ61gNV9KGb8thSsNjpSL0n8PARn9HuZOnIxN0hoP+VmmDGMN5t9UJ0Z" crossorigin="anonymous">
</head>
<body>


<div class="container">
    <div sec:authorize="isAuthenticated()">
        <form id="logoutForm" method="POST" th:action="@{/logout}">
            <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>
        </form>
        <h2>Welcome <span sec:authentication="name"></span> |
            <a onclick="document.forms['logoutForm'].submit()">
                <button class="btn btn-primary btn-lg" type="submit"><i class="fa fa-sign-out" aria-hidden="true"></i>Log out</button>
            </a>
        </h2>
    </div>
</div>

<!-- Navigation -->
<nav class="navbar navbar-expand-lg navbar-dark bg-dark static-top">
    <div class="container">
        <a class="navbar-brand" href="/"><p th:text="#{schoolbook.title}"></p></a>
        <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarResponsive"
                aria-controls="navbarResponsive"
                aria-expanded="false" aria-label="Toggle navigation">
            <span class="navbar-toggler-icon"></span>
        </button>
        <div class="collapse navbar-collapse" id="navbarResponsive">
            <ul class="navbar-nav ml-auto">
                <li class="nav-item ">
                    <a class="nav-link" href="/">Home   </a>
                </li>
                <li class="nav-item">
                    <a class="nav-link" th:href="@{/showstudent}">Show student list</a>
                </li>
                <li class="nav-item active">
                    <a class="nav-link" href="#">Show courses list
                        <span class="sr-only">(current)</span>
                    </a>
                </li>
                <li class="nav-item">
                    <a class="nav-link" href="#">Contact</a>
                </li>
            </ul>
        </div>
    </div>
</nav>

<div th:switch="${courses}" class="container my-5">
    <div class="row">
        <form th:action="@{/searchcourses}" method="get">
            <input type="text" name="keyword" th:value="${keyword}" size="50" >
            <button type="submit" class="btn btn-primary fa fa-search"> Search</button>
            <button type="submit" class="btn btn-primary" > Reset</button>
        </form>
        <table class="table table-striped table-responsive-md">
            <thead>
            <tr>
                <th>Name</th>
                <th>Modification</th>
            </tr>
            </thead>
            <tbody>
            <tr th:each="course : ${courses}">
                <td th:text="${course.lessonName}"></td>
                <td style="text-align: right;">
                    <div class="btn-group open">
                        <a class="btn btn-primary fa fa-graduation-cap" href="#"> Course</a>
                        <a class="btn btn-primary" data-toggle="dropdown" href="#">
                            <span class="fa fa-caret-down"></span>
                        </a>
                        <ul class="dropdown-menu">
                            <li><a th:href="@{/edit/courses/{id}(id=${course.id})}"  class="fa fa-pencil"> Edit</a></li>
                            <i class="fas fa-horizontal-rule"></i>
                            <li><a th:href="@{/delete/courses/{id}(id=${course.id})}"class="fa fa-trash"> Delete</a></li>
                        </ul>
                    </div>
                </td>
            </tr>
            </tbody>
        </table>


            <button type="button" data-toggle="modal" data-target="#myModal" class="fa fa-graduation-cap btn btn-primary">
             Add Course
            </button>

        <div class="modal fade" id="myModal" 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 Classroom</h5>
                        <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                            <span aria-hidden="true">&times;</span>
                        </button>
                    </div>
                    <form action="#" th:action="@{/addcourse}" th:object="${course}" method="post">
                        <script th:inline="javascript" th:if="${#fields.hasErrors('*')}">$("#myModal").modal("show");</script>
                        <div class="modal-body">
                            <legend>Add Course</legend>
                            <div class="form-group">
                                <label for="lessonName" class="col-form-label">Name</label>
                                <input type="text" th:field="*{lessonName}" class="form-control" id="lessonName" placeholder="lessonName">
                                <div class="text text-danger" th:if="${#fields.hasErrors('lessonName')}" th:errors="*{lessonName}">
                                </div>
                            </div>
                            <div class="form-group">
                                <label for="lessonYear" class="col-form-label">lessonYear</label>
                                <input type="text" th:field="*{lessonYear}" class="form-control" id="lessonYear" placeholder="lessonYear">
                                <div class="text text-danger" th:if="${#fields.hasErrors('lessonYear')}" th:errors="*{lessonYear}">
                                </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>
                        </div>
                    </form>
                </div>
            </div>
        </div>
    </div>
</div>


<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js" integrity="sha384-9/reFTGAW83EW2RDu2S0VKaIzap3H66lZH81PoYlFhbGU+6BZp6G7niu735Sk7lN" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js" integrity="sha384-B4gt1jrGC7Jh4AgTPSdUtOBvfO8shuf57BaghqFfPlYxofvL8/KUEfYiJOMMV+rV" crossorigin="anonymous"></script>

</body>
</html>

Java:
    @GetMapping("/createCourses")
    public String createCourses(Model model) {
        model.addAttribute("course", new Course());
        return "table-courses";
    }

    @PostMapping("/addcourse")
    public String addCourse(@Valid @ModelAttribute("Course")Course course, BindingResult result, RedirectAttributes atts, Model model) {
        coursesValidator.validate(course, result);
        if (result.hasErrors()) {
atts.addAttribute("hasErrors", true);
atts.addAttribute("lessonName", "Duplicated");
model.addAttribute("hasErrors", true);
model.addAttribute("lessonName", "Duplicated");
            atts.addAttribute("course", course);
            model.addAttribute("course", course);
            return "table-courses";
        }

        coursesRepository.save(course);
        return  "redirect:/table-courses";
    }
 
Zuletzt bearbeitet:
Nur so vom lesen her, du solltest dir mal AJAX anschauen. JQuery nutzt du schon, Da sollte das kein Problem darstellen.

Ob Themeleaf da direkt was bietet kann ich dir nicht sagen.
 
Zurück
Oben