0

My goal is to cycle through a list of objects, some to be displayed on the screen, others to be passed into a form as an object of which I can define certain aspects and then return to the controller the object and attribute to be modified.

The problem with the following approach is that the object in the list is not passed correctly to the form and thus gives an error because it is trying to make changes to a non-existent object.

If, on the other hand, I try to pass it as an object via ModelAndView it obviously works but does not have all the characteristics of the object I passed via the list.

Controller

@GetMapping("/")
    public ModelAndView home() throws IOException {
        ModelAndView mv = new ModelAndView();
        mv.setViewName("home");

        List<Comics> allComics = cs.getAll();
        
        mv.addObject("comics", allComics);
        return mv;
    }

@PostMapping("/update")
    public ModelAndView update(Comics com, @RequestParam("attr") String attr) throws IOException {
        ModelAndView mv = new ModelAndView();
        
        com.setLastRead(attr);
        
        cs.updateAttributes(com);
        
        mv.setViewName("home");
        List<Comics> allComics = cs.getAll();
        mv.addObject("comics", allComics);
        return mv;
    }

home.html

<html xmlns:th="http://www.thymeleaf.org">
<tr th:each="comic : ${comics}">
                    <td th:text="${comic.title}"></td>
                    <td th:text="${comic.lastChapter}"></td>
                    <td>
                    <a th:href="${comic.lastChapterLink}" target="_blank"
                    role="button" class="btn btn-md btn-block btn-info"> Link
                    </a>
                    </td>
                        <td></td>
                    <td>
                        <form th:action="@{/update}" th:object="${comic}" method="post">
                            <input type="text" name="attr" id="attr"/>
                            <button type="submit">Sub</button>
                        </form>
                    </td>
</tr>

PS: I cut out the head of the html page because it was full of non-relevant CDNs

How can I integrate Spring MVC with Thymeleaf to achieve the result whereby passing a list of objects can be displayed on the screen and used for other purposes within the html page without throwing errors?

Obviously if you know of more efficient methods to achieve the result I'm listening; I only used this method because I didn't know of any others.

Thank you

Answer to @RafaeldaSilva:

I agree, but that does not solve the problem. Let me explain: the attribute I am going to modify through the form already has its name to allow what you wrote. But the object iterated through:

tr th:each="comic : ${comics}">

cannot be passed directly as input, as it is a value that is taken from a list and exists individually only in the html page. One might think of passing it as hidden input, but in this case the result would be the same (I have tried):

<form th:action="@{/update}" th:object="${comic}" method="post">
                            <input type="hidden" value="${comic}" name="com"/>
                            <input type="text" name="attr" id="attr"/>
                            <button type="submit">Sub</button>
</form>

@PostMapping("/update")
    public ModelAndView update(@RequestParam("com") Comics com, @RequestParam("attr") String attr) throws IOException {
        ModelAndView mv = new ModelAndView();
        
        com.setLastRead(attr);
        
        System.out.println("Comic: " + com);
        
        cs.updateAttributes(com);
        
        mv.setViewName("home");
        List<Comics> allComics = cs.getAll();
        mv.addObject("comics", allComics);
        return mv;
    }

Error: [org.springframework.web.bind.MissingServletRequestParameterException: Required request parameter 'com' for method parameter type Comics is present but converted to null]

3
  • your code looks right, could you enter the error you are getting? so I can analyze better.. Commented Jun 1, 2022 at 13:26
  • @RafaeldaSilva sure, the error it generates is: org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.springframework.orm.jpa.JpaSystemException: ids for this class must be manually assigned before calling save(): com.eug.comicsarchive.model.Comics;
    – Eugenio
    Commented Jun 1, 2022 at 13:56
  • @RafaeldaSilva The problem is that the comic object as long as it is in the html page is read correctly, when it is sent back to the controller, every one of its fields is null, therefore also its id.
    – Eugenio
    Commented Jun 1, 2022 at 13:58

1 Answer 1

1

try removing the type="hidden" to see what is present in this input, as I understand you are inserting an object by doing value="${comic}", this way the input should not send the value wanted..

change this: <input type="hidden" value="${comic}" name="com"/>

for this: <input type="text" value="${comic}" name="com"/>

so you can see what the form is sending to the controller, I believe it's the object's memory path, and not the data that exists in it.

in the input you must inform the attributes of the object, not the complete object..

9
  • I tried to answer you by editing the question because there was not enough space below.
    – Eugenio
    Commented Jun 1, 2022 at 15:15
  • I just changed the answer, try what I said, because I believe you are reporting the values wrongly.. confirm me here what appears in the input. Commented Jun 1, 2022 at 15:45
  • you are right, the input is: "${comic}" so it is not really possible to pass an object but only parameters? thanks
    – Eugenio
    Commented Jun 1, 2022 at 15:53
  • 1
    exactly, because thymeleaf is a teplate engine, it loads the values and sends it to the browser, if you pass an entire object, it will assemble the html and send it to the browser and the browser will not be able to interpret it correctly. Commented Jun 1, 2022 at 15:57
  • 1
    to use the th:field, it would be like this th:field="*{title}" the * character is used to refer to the object of th:object, and whatever is inside {} is the object's attribute. Commented Jun 1, 2022 at 17:48

Not the answer you're looking for? Browse other questions tagged or ask your own question.