在 Thymeleaf 中动态使用片段 - Spring Boot/动态重新加载页面的一部分 onChange/onClick whatever

问题描述 投票:0回答:0

如标题所示,我正在尝试创建一个页面,更准确地说是一个表单,当页面的元素发生更改时必须重新加载它的一部分(onChange)

我在前端使用 Thymeleaf,在后端使用 Spring Boot。

理论上在 Thymeleaf 中,我们应该直接通过控制器发送片段并将其作为完整片段接收。

通过将

model.addAttribute()
放入片段的 Get 请求中,+ 在 Thymeleaf 端很好地制作了片段的页面后,它应该会自动执行操作,也就是说,当我'我打算通过获取或通过 ajax 进行调用以接收响应(片段)。

所以我只需要通过 getElementById 获取我想替换的页面部分并执行加载(响应)

问题是我得到的是字符串而不是构造的片段

也就是说,我得到

fragments/underHeadingList :: input
,作为一个字符串。我想这行不通。

但是,当我放的时候,

<div th:replace="fragments/underHeadingList :: input"></div>"

直接在我的代码中,它可以工作并调用片段

问题当然是这个片段应该显示的列表会根据在更改期间选择的元素而变化

这是我的代码:

[控制器]

import be.mutualit.dto.UnderHeadingDTO;
import be.mutualit.service.UnderHeadingService;

import java.util.List;
import java.util.Locale;

import javax.servlet.http.HttpSession;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
@RequestMapping("underHeading")
public class UnderHeadingController {

    private final UnderHeadingService underHeadingService;

    public UnderHeadingController(UnderHeadingService underHeadingService) {
        this.underHeadingService = underHeadingService;
    }
    
    @GetMapping("getAllLinkToHeadingID")
    @ResponseBody
    public String getAllLinkToHeadingID(Model model, HttpSession session) {
        Locale locale = (Locale) session.getAttribute("locale");
        List<UnderHeadingDTO> allLinkToHeadingIDByLanguage = underHeadingService.getAllLinkToHeadingIDByLanguage(713, locale);
        model.addAttribute("underHeadingList", allLinkToHeadingIDByLanguage);
        return "fragments/underHeadingList :: input";
    }

}

[片段 html]

<!DOCTYPE html>
<html lang="eng" xmlns:th="http://www.thymeleaf.org">
<!--/*@thymesVar id="underHeadingList" type="java.util.List<be.mutualit.dto.UnderHeadingDTO>"*/-->
<!--/*@thymesVar id="underHeading" type="be.mutualit.dto.UnderHeadingDTO"*/-->
<head>
    <title></title>
</head>
<div th:fragment="input">
    <label for="underHeadingSelect" th:text="#{addActionProblem.underHeading}"></label>
    <select id="underHeadingSelect" name="underHeadingSelect" th:field="*{underHeadingID}" style="font-size: 12px;">
        <option th:each="underHeading : ${underHeadingList}"
                th:value="${underHeading.id}"
                th:text="${underHeading.label}">
        </option>
    </select>
    <div class="alert alert-warning" th:if="${#fields.hasErrors('underHeadingID')}" th:errors="*{underHeadingID}"></div>
</div>
</html>

[JS部分]

function onChangeSelectHeading() {
$.get('/underHeading/getAllLinkToHeadingID', function (fragment) {
    console.log(fragment)
    $("#underHeadingDiv").replaceWith(fragment);
});

}

[页]

<!DOCTYPE html>
<html lang="eng" xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{layouts/layout}">
<!--/*@thymesVar id="headingList" type="java.util.List<be.mutualit.dto.HeadingDTO>"*/-->
<!--/*@thymesVar id="heading" type="be.mutualit.dto.HeadingDTO"*/-->
<!--/*@thymesVar id="actionList" type="java.util.List<be.mutualit.dto.HeadingDTO>"*/-->
<!--/*@thymesVar id="action" type="be.mutualit.dto.HeadingDTO"*/-->
<!--/*@thymesVar id="contactList" type="java.util.List<be.mutualit.dto.HeadingDTO>"*/-->
<!--/*@thymesVar id="contact" type="be.mutualit.dto.HeadingDTO"*/-->
<!--/*@thymesVar id="underHeadingList" type="java.util.List<be.mutualit.dto.UnderHeadingDTO>"*/-->
<!--/*@thymesVar id="actionProblem" type="be.mutualit.dto.ActionProblemForm"*/-->
<body>
<div id="container_main" class="container">
    <div id="content" layout:fragment="content">
        <div class="code">
            <form id="formAddActionProblem" action="#" th:action="@{/addActionProblem}" method="post" th:object="${actionProblem}">
                <div class="block mb-3 mt-2">
                    <label for="id">Id</label>
                    <input id="id" disabled type="text" th:field="*{id}"/>
                    <div class="alert alert-warning" th:if="${#fields.hasErrors('id')}" th:errors="*{id}"></div>
                </div>
                <div class="block mb-4">
                    <label for="creationDate" th:text="#{addActionProblem.date}"></label>
                    <input id="creationDate" type="datetime-local" th:field="*{creationDate}"/>
                    <div class="alert alert-warning" th:if="${#fields.hasErrors('creationDate')}" th:errors="*{creationDate}"></div>
                </div>
                <p class="mb-1" style="font-size: 13px" th:text="#{addActionProblem.underTitle.duration}"></p>
                <div class="block mb-4">
                    <div class="row">
                        <div class="col-1"><label for="hourDuration" th:text="#{addActionProblem.hour}"></label>
                            <input style="width: 60px;" id="hourDuration" type="number" min="0" th:field="*{hourDuration}"/>
                            <div class="alert alert-warning" th:if="${#fields.hasErrors('hourDuration')}" th:errors="*{hourDuration}"></div>
                        </div>
                        <div class="col-1"><label for="minuteDuration" th:text="#{addActionProblem.minute}"></label>
                            <input style="width: 60px;" id="minuteDuration" type="number" min="0" max="60" th:field="*{minuteDuration}"/>
                            <div class="alert alert-warning" th:if="${#fields.hasErrors('minuteDuration')}" th:errors="*{minuteDuration}"></div>
                        </div>
                    </div>
                </div>
                <p class="mb-1" style="font-size: 13px" th:text="#{addActionProblem.underTitle.fileType}"></p>
                <div class="block mb-3">
                    <label for="headingSelect" th:text="#{addActionProblem.heading}"></label>
                    <select id="headingSelect" name="headingSelect" th:field="*{headingID}" th:onchange="onChangeSelectHeading()" style="font-size: 12px;">
                        <option th:each="heading : ${headingList}"
                                th:value="${heading.id}"
                                th:text="${heading.label}">
                        </option>
                    </select>
                    <div class="alert alert-warning" th:if="${#fields.hasErrors('headingID')}" th:errors="*{headingID}"></div>
                </div>
                <div class="block mb-3">
                    <div id="underHeadingDiv">
                        <div th:replace="fragments/underHeadingList :: input"></div>
                    </div>
                </div>
                <div class="block mb-3">
                    <label for="actionSelect" th:text="#{addActionProblem.action}"></label>
                    <select id="actionSelect" name="actionSelect" th:field="*{actionID}" style="font-size: 12px;">
                        <option th:each="action : ${actionList}"
                                th:value="${action.id}"
                                th:text="${action.label}">
                        </option>
                    </select>
                    <div class="alert alert-warning" th:if="${#fields.hasErrors('actionID')}" th:errors="*{actionID}"></div>
                </div>
                <div class="block mb-3">
                    <label for="contactSelect" th:text="#{addActionProblem.contactMode}"></label>
                    <select id="contactSelect" name="contactSelect" th:field="*{contactTypeID}" style="font-size: 12px;">
                        <option th:each="contact : ${contactList}"
                                th:value="${contact.id}"
                                th:text="${contact.label}">
                        </option>
                    </select>
                    <div class="alert alert-warning" th:if="${#fields.hasErrors('contactTypeID')}" th:errors="*{contactTypeID}"></div>
                </div>
                <div class="mb-3">
                    <p class="mb-1" th:text="#{addActionProblem.incomingOutgoing}"></p>
                    <input id="incoming" name="incomingOutgoing" type="radio" th:text="' ' + #{addActionProblem.incoming} + ' '"
                           th:field="*{incomingOutgoing}" value="E"/>
                    <label for="incoming"></label>
                    <input id="outgoing" name="incomingOutgoing" type="radio" th:text="' ' + #{addActionProblem.outgoing} + ' '"
                           th:field="*{incomingOutgoing}" value="S"/>
                    <label for="outgoing"></label>
                    <div class="alert alert-warning" th:if="${#fields.hasErrors('incomingOutgoing')}" th:errors="*{incomingOutgoing}"></div>
                </div>
                <div class="block mb-3">
                    <label for="comment" th:text="#{addActionProblem.comment}"></label>
                    <textarea id="comment" style="width: 446px; height: 126px;" rows="8" cols="6" th:field="*{comment}"></textarea>
                    <div class="alert alert-warning" th:if="${#fields.hasErrors('comment')}" th:errors="*{comment}"></div>
                </div>
                <div class="float-end">
                    <img class="buttonFormPicture"
                         th:src="@{images/save.png}"
                         alt="save button"/>
                    <button class="buttonForm" type="submit" th:text="#{addActionProblem.save}"></button>
                    &nbsp&nbsp&nbsp
                    <img class="buttonFormPicture"
                         th:src="@{images/cancel.png}"
                         alt="cancel button"/>
                    <button class="buttonForm" type="button" th:onclick="onClickCancelButton()" th:text="#{addActionProblem.cancel}"></button>
                </div>
                <div th:if="${message}" th:text="${message}" th:class="${'alert ' + alertClass}"></div>
                <br/><br/>

            </form>
        </div>
    </div>
</div>
</body>
</html>

ActionProblemForm (DTO)

import java.io.Serial;
import java.io.Serializable;
import java.time.LocalDateTime;

import javax.validation.constraints.Max;
import javax.validation.constraints.Min;

import org.springframework.format.annotation.DateTimeFormat;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class ActionProblemForm implements Serializable {

    @Serial
    private static final long serialVersionUID = -4259040663789461901L;

    private int id;

    @DateTimeFormat(pattern = "yyyy-MM-dd'T'HH:mm")
    private LocalDateTime creationDate;

    @Min(value = 0, message = "{addActionProblem.constraint.hour.min}")
    private int hourDuration;

    @Min(value = 0, message = "{addActionProblem.constraint.minute.min}")
    @Max(value = 60, message = "{addActionProblem.constraint.minute.max}")
    private int minuteDuration;

    private int headingID;

    private int underHeadingID;

    private int actionID;

    private int contactTypeID;

    private char incomingOutgoing;

    private String comment;
}

UnderHeadingDTO

import java.io.Serial;
import java.io.Serializable;

import lombok.AllArgsConstructor;
import lombok.Data;

@Data
@AllArgsConstructor
public class UnderHeadingDTO implements Serializable {

    @Serial
    private static final long serialVersionUID = -6048713942983512203L;

    private int id;
    private String label;
}

编辑:

当我从片段代码中删除“表单部分”时,代码正在运行并且不再显示字符串。

所以现在的问题是我需要找到一种方法来提交表单,同时从片段中获取数据。

th:field="*{underHeadingID}"

因为在我的片段中没有这部分,我不会在我的控制器中接收数据

javascript ajax spring-boot thymeleaf
© www.soinside.com 2019 - 2024. All rights reserved.