@postya

Как показать уведомление с анимацией без перезагрузки встраницы после сохранения формы в Spring Boot?

Приложеине на Spring Boot + Thymeleaf

Есть форма. После нажатия на кнопку происходит сохранение данных в БД из полей , редирект на эту же страницу и
появляется уведомление на этой же странице,что сохранение успешно выполнено.
Всё работает отлично, уведомление появляется, но мне не нравится,что происходит перезагрузка страница и это уведомление статически появляется(резко). Я бы хотел чтобы этот процесс был без перезагрузки и уведомление плавно появлялось, с какой-нибудь анимацией. Вомзонжо нужно применить AJAX и Javascript, но я не знаю как это сделать.

Как можно это реализовать?

Controller:

@PostMapping("/sketches/add")
    public String addSketch(
                            @Valid Sketch sketch,
                            BindingResult result,
                            ModelMap model,
                            RedirectAttributes redirectAttributes) {
        redirectAttributes.addFlashAttribute("message", "Failed");
        redirectAttributes.addFlashAttribute("alertClass", "alert-danger");
        if (result.hasErrors()) {
            return "admin/add-sketch";
        }
       sketchRepository.save(sketch);
        redirectAttributes.addFlashAttribute("message", "Success!");
        redirectAttributes.addFlashAttribute("alertClass", "alert-success");
        return "redirect:/admin/sketches/add";
    }


Форма в HTML:

<form action="#" th:action="@{/admin/sketches/add}" th:object="${sketch}" method="post" id="save-sketch">
        <div class="add-sketch">
            <div class="title">
                <div class="title-text">
                    <p>Title
                        <span th:if="${#fields.hasErrors('title')}" th:errors="*{title}" class="error"></span>
                    </p>
                    <input type="text" class="title-input" th:field="*{title}">
                </div>
                <div class="title-file">
                    <label for="file-input">
                        <img th:src="@{/images/add image.png}" alt="upload image">
                    </label>
                    <input id="file-input" type="file"/>
                </div>
                <span id="image-text">No file chosen, yet</span>
            </div>

            <!--SKETCH TEXT====================================-->
            <div class="sketch-text">
                <p>Sketch Text
                    <span th:if="${#fields.hasErrors('text')}" th:errors="*{text}" class="error"></span>
                </p>
                <textarea name="sketch-area" id="" cols="55" rows="6" th:field="*{text}"></textarea>
            </div>

            <!--DROPDOWN-->
            <div class="select">
                <select name="select-category" id="select-category" th:field="*{category}">
                    <option value="Buttons">Buttons</option>
                    <option value="Potentiometers">Potentiometers</option>
                    <option value="Encoders">Encoders</option>
                    <option value="Leds">Leds</option>
                </select>
            </div>

            <span th:if="${#fields.hasErrors('category')}" th:errors="*{category}" class="error"></span>

            <!--ADD GIF=====================================-->
            <input type="file" id="gif-file" hidden="hidden">
            <button type="button" id="gif-button">Add GIF<i class="fas fa-image"></i></button>
            <span id="gif-text">No file chosen, yet</span>

            <div class="save-sketch">
                <button type="submit" class="save-sketch-button">Save Sketch</button>
            </div>
            <div th:if="${message}" th:class="${'alert ' + alertClass}" class="success-message animated slideInDown">
                <div class="success-content">
                    <i class="fas fa-check-circle"></i>
                    <p th:text="${message}"></p>
                </div>
            </div>

        </div>
    </form>


Блок с уведомлением в форме, который показывается или не показывается согласно ответа от контроллера:
<div th:if="${message}" th:class="${'alert ' + alertClass}" class="success-message animated slideInDown">
                <div class="success-content">
                    <i class="fas fa-check-circle"></i>
                    <p th:text="${message}"></p>
                </div>
            </div>
  • Вопрос задан
  • 548 просмотров
Пригласить эксперта
Ответы на вопрос 2
azerphoenix
@azerphoenix Куратор тега Spring
Java Software Engineer
Здравствуйте!
Вы все правильно предположили насчет Ajax & JS + CSS.
Писать код с нуля не буду, а лишь расскажу вам этапы для достижения желаемого...
1) Создайте метод, который на ajax запрос будет возвращать @ResponseBody, либо создайте контроллер и добавьте аннотацию @RestController
2) Перед закрывающим тегом </body> добавьте js код для аякс.
https://ruseller.com/jquery.php?id=11
https://api.jquery.com/jquery.ajax/
3) Далее в контроллере обрабатываете запрос и возвращаете String или например, Map<String, String> с нужными данными.
4) В ajax на событие success показываете ваш блок с анимацией.

Теперь, про саму анимацию...
Анимацию можно сделать средствами CSS или JS.
Вот, пример CSS
Допустим вот, ваш блок и он по умолчанию скрыт
<div class="notify" style="display:none;"></div>
При success делаете этот блок show() (видимым).
Показать - https://api.jquery.com/show/
Скрыть - https://api.jquery.com/hide/

Остается только добавить анимацию - @keyframes
https://www.w3schools.com/css/css3_animations.asp

Вот, готовые библиотеки -
https://stephanwagner.me/jBox
https://notifyjs.jpillora.com/
Ответ написан
@postya Автор вопроса
Нашёл библиотеку Toastr, всё работает так, как надо.
Вот ,что имею на выходе:

Метод,который сохраняет поля в БД:

@PostMapping("/sketches/add")
    public String addSketch(
                            @Valid Sketch sketch,
                            BindingResult result,
                            RedirectAttributes redirectAttributes) {

        redirectAttributes.addFlashAttribute("action", "save");
        if (result.hasErrors()) {
            return "admin/add-sketch";
        }
       sketchRepository.save(sketch);
        return "redirect:/admin/sketches/add";
    }


Подключение бибилотеки Toastr в html файле:

<link rel="stylesheet" th:href="@{/libs/toastr/toastr.min.css}">

    <script th:src="@{/libs/jquery/jquery-3.4.1.min.js}"></script>
    <script defer th:src="@{/libs/toastr/toastr.min.js}"></script>
    <script defer th:src="@{/js/add-sketch.js}"></script>


Настройки для библиотеки Toastr в отдельном файле add-sketch.js:

/*TOASTR OPTIONS*/
toastr.options = {
    "closeButton": false,
    "debug": false,
    "newestOnTop": false,
    "progressBar": false,
    "positionClass": "toast-bottom-right",
    "preventDuplicates": false,
    "onclick": null,
    "showDuration": "300",
    "hideDuration": "1000",
    "timeOut": "2000",
    "extendedTimeOut": "1000",
    "showEasing": "swing",
    "hideEasing": "linear",
    "showMethod": "fadeIn",
    "hideMethod": "fadeOut"
};


Вызов скрипта библиотеки в конце html файла:

<script th:inline="javascript">
    $(document).ready(function () {
        var action = [[${action}]];
        if (action === 'save') {
            toastr["success"]("Success!")
        }
    });
</script>
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы