spring-mvcspring-restcontrollerspring-form

Spring MVC pass object from list to post-endpoint


I have a spring-controller with a post-endpoint that receives a WordDto. Another get-endpoint puts a list of WordDtos in the ModelMap and shows a jsp-file. In the jsp-file, I show each entry of the list in a row of a table. Each row has additionally a button, that should call the post-endpoint with the WordDto for that row.

But I don't know, how to pass the WordDto from the row correctly to the post-endpoint.

Endpoints

    @GetMapping("/generate")
    public String generateWords(ModelMap model, @RequestParam(value = "language", defaultValue = "-1", required = false) long language, @RequestParam(value = "amount", defaultValue = "-1", required = false) int amount)
    {
        model.put("language", language);
        model.put("amount", amount);

        LanguageData languageData = languageService.getLanguageData(language);

        model.put("languageName", languageData.getName());
        model.put("words", generationService.generateWords(language, amount));

        return "list-words";
    }

    @PostMapping("word")
    public String saveWord(ModelMap model, HttpServletRequest request, @Valid WordDto singleWord)
    {
        translationService.saveOrGetWord(singleWord);

        return "redirect:" + request.getHeader("Referer");
    }

jsp-file

<body>
    <%--@elvariable id="languageName" type="java.lang.String"--%>
    <h1>Generated words with '${languageName}'</h1>
    <table class="table">
        <thead>
        <tr>
            <th>Word</th>
        </tr>
        </thead>
        <tbody>
        <%--@elvariable id="words" type="java.util.List"--%>
        <c:forEach items="${words}" var="singleWord">
            <tr>
                <td>
                        ${singleWord.word}
                </td>
                <td>
                    <form:form method="post" action="word" modelAttribute="singleWord.word">
                        <form:input type="hidden" path="languageId"/>
                        <form:input type="text" path="word"/>
                    </form:form>
                </td>
            </tr>
        </c:forEach>
        </tbody>
    </table>
</body>

How can I send the WordDto, that I have in a row in the jsp-table, to the /word endpoint?


Solution

  • I got it working, but only with different approach, that is (in my eyes) not as nice as I originally planned. The new version takes two parameters, instead of the entire object at once.

    I adjusted the table to look like this:

            <tbody>
            <%--@elvariable id="words" type="java.util.List"--%>
            <c:forEach items="${words}" var="singleWord" varStatus="status">
                <tr>
                    <form:form method="post" action="word">
                        <input type="hidden" name="languageId" value="${singleWord.languageId}"/>
                        <td>
                            <label>
                                <input type="text" name="word" value="${singleWord.word}"/>
                            </label>
                        </td>
                        <td>
                                <%--TODO: Add button to show translation page for this word (Should also save the word before showing the page, if it is not yet saved)--%>
                        </td>
                        <td>
                            <input type="submit" class="btn-success" value="Save">
                        </td>
                    </form:form>
                </tr>
            </c:forEach>
            </tbody
    

    And the endpoint had to be modified too:

        @PostMapping("word")
        public String saveWord(HttpServletRequest request, @RequestParam(value = "languageId") long languageId, @RequestParam(value = "word") String word)
        {
            translationService.saveOrGetWord(new WordDto(languageId, word));
    
            return "redirect:" + request.getHeader("Referer");
        }