Thymeleaf:表单提交中的更新表

时间:2019-05-22 17:11:53

标签: java spring thymeleaf

我有一个视图,其中有一个用于创建新的Exercise对象的窗体和一个用于显示所有练习的表格。现在,我希望该表随新创建的练习自动刷新。当前它将表显示为空,直到我再次手动转到localhost:8080/exercise

这是我的控制器:

@Controller
public class ExerciseController {

    @Autowired
    private ExerciseService exerciseService;

    @Autowired
    private ModelMapper modelMapper;

    @GetMapping("/exercise")
    public String exerciseView(final Model model) {

        List<Exercise> exerciseList = exerciseService.getAllExercises();

        model.addAttribute("exerciseDTO", new ExerciseDTO());
        model.addAttribute("title", "Create an Exercise");
        model.addAttribute("exercises", exerciseList);
        return "exercise";
    }

    @PostMapping("/exercise")
    public String createExercise(@ModelAttribute final ExerciseDTO exerciseDto) {

        final Exercise exercise = this.modelMapper.map(exerciseDto, Exercise.class);

        this.exerciseService.createExercise(exercise);
        return "exercise";
    }
}

还有我的百里香模板:

<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head th:replace="template :: head"></head>
<body>
    <header th:replace="template :: navbar"></header>
    <h1>Form</h1>
    <form action="#" th:action="@{/exercise}" th:object="${exerciseDTO}" method="post">
        <p>Name: <input type="text" th:field="*{name}" /></p>
        <p>Description: <input type="text" th:field="*{description}" /></p>
        <p>Exercise type:
            <select th:field="*{type}" id="typeSelector">
                <option th:each="type : ${T(com.nsterdt.routinierbackend.data.enums.ExerciseType).values()}"
                th:value="${type}" th:text="${type.displayName}">
                </option>
            </select>
        </p>
        <p id="bpmRow">BPM: <input type="number" th:field="*{bpm}" id="bpmInput" /></p>
        <p><input type="submit" value="Submit" /> <input type="reset" value="Reset" /></p>
    </form>

    <br>

    <table>
        <tr>
            <th>Name</th>
            <th>Description</th>
            <th>Type</th>
            <th>BPM</th>
        </tr>
        <tr th:each="exercise : ${exercises}">
            <td th:text="${exercise.name}"></td>
            <td th:text="${exercise.description}"></td>
            <td th:text="${exercise.type}"></td>
            <td th:text="${exercise.bpm}"></td>
        </tr>
    </table>
</body>
</html>

现在,我认为返回“运动”的createExercise方法将调用exerciseView方法,从而调用exerciseService.getAllExercises()。有没有办法实现此功能?还是有一种更好的方法,而无需重新加载整个页面?

2 个答案:

答案 0 :(得分:1)

要在不刷新页面的情况下提供数据,您需要诸如Angular或React之类的客户端技术。或普通的旧javascript。但是您无法在无页面刷新的Spring MVC中向页面提供新数据。

答案 1 :(得分:1)

您可以使用AJAX将请求从客户端发送到服务器端并接收答案,而无需刷新页面。

不幸的是,我没有足够的时间,并且我无法完成代码,但是您可以执行以下操作:

function submitItems() {

    var contextPath = $("meta[name='ctx']").attr("content");

    var exerciseDto = {};
    exerciseDto.name = $("#name").val();
    exerciseDto.description = $("#description").val();
    exerciseDto.typeSelector = $("#typeSelector).val();
    exerciseDto.bpmInput = $("#bpmInput").val();

    $.ajax({
        dataType : "json",
        type : "post",
        url : contextPath + "/exercise",
        data : JSON.stringify(exerciseDto),
        cache : false,
        contentType : "application/json",
        beforeSend : function(xhr) {
            xhr.setRequestHeader(header, token);
        },
        success : function(data) {
            console.log(data);
            //HERE YOU NEED ACTION TO UPDATE TABLE.
        },
        error : function(jqXHR, textStatus, errorThrown) {
            console.log(jqXHR.responseText);
            console.log('getJSON request failed! ' + textStatus);
        }
    });
}

然后您的视图必须是这样的:

<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head th:replace="template :: head"></head>
<body>
    <header th:replace="template :: navbar"></header>
    <h1>Form</h1>
    <form onsubmit="submitItems();return false;">
        <p>Name: <input id="name" type="text" /></p>
        <p>Description: <input id="description" type="text" /></p>
        <p>Exercise type:
            <select th:field="*{type}" id="typeSelector">
                <option th:each="type : ${T(com.nsterdt.routinierbackend.data.enums.ExerciseType).values()}"
                th:value="${type}" th:text="${type.displayName}">
                </option>
            </select>
        </p>
        <p id="bpmRow">BPM: <input type="number" id="bpmInput" /></p>
        <p><input type="submit" value="Submit" /> <input type="reset" value="Reset" /></p>
    </form>

    <br>

    <table>
        <tr>
            <th>Name</th>
            <th>Description</th>
            <th>Type</th>
            <th>BPM</th>
        </tr>
        <tr th:each="exercise : ${exercises}">
            <td th:text="${exercise.name}"></td>
            <td th:text="${exercise.description}"></td>
            <td th:text="${exercise.type}"></td>
            <td th:text="${exercise.bpm}"></td>
        </tr>
    </table>
</body>
</html>

请记住,您需要创建一个将更新表的JS操作。有很多方法可以做到这一点(您可以将新数据推送到数据表或使用JS函数添加新内容)。

我希望这可以帮助您更多地了解AJAX的工作原理。

PS。您还必须更新控制器以返回结果,在您的实例中将是

@PostMapping("/exercise")
    public createExerciseDomainTYPEHERE createExercise(@RequestBody final ExerciseDTO exerciseDto) {

        final Exercise exercise = this.modelMapper.map(exerciseDto, Exercise.class);

        //this.exerciseService.createExercise(exercise);
        //return "exercise";
        return this.exerciseService.createExercise(exercise);
    }

您将不得不更改此行

  

public createExerciseDomainTYPEHERE createExercise(@RequestBody final ExerciseDTOexerciseDto){

到您的createExercise域类型。