0

I have a list of time entry for which i want to create a modal for in my page. Each time entry will have it's own modal. Inside of these modal, i want to put a form. Each form must point to one of the time entry backing bean.

Here is the relevant part of the endpoint attach to this page

@GetMapping("/time/{year}/{month}/{dayOfTheMonth}")
  public String show(
    ModelMap model,
    @PathVariable Integer year,
    @PathVariable Integer month,
    @PathVariable Integer dayOfTheMonth
  ){
   ....
    var editEntryForms = entries
      .stream()
      .map(EditEntryForm::new)
      .collect(Collectors.toList());

    model.addAttribute("editEntryForms", editEntryForms);


    return "timesheet/show";
  }

My form backing object

@Data
class EditEntryForm {

  public EditEntryForm(TimeEntry timeEntry){
    id = timeEntry.getId();
    description = timeEntry.getDescription();
  }

  private Long id;
  private String description;
}

And the (relevant parts of the) template

<div class="ui modal"
     th:each="editEntryForm : ${editEntryForms}"
     th:id="${'edit-entry-modal-'+editEntryForm.id}">
  <div class="header">
    Edit time entry
  </div>
  <div class="content">
    <form class="ui form"
          th:object="${editEntryForm}"
          th:classappend="${#fields.hasErrors('*')} ? error"
          th:id="${'edit-entry-form'+ editEntryForm.id}"
          th:action="@{/time/{year}/{month}/{day}/{entryId}(year=${year}, month=${month}, day=${dayOfTheMonth}, entryId=${editEntryForm.id})}"
          method="POST">
...
    </form>
  </div>
  <div class="actions">
   <button class="ui approve primary button" form="add-entry-form">Update entry</button>
   <div class="ui cancel button">Cancel</div>
   <div class="ui right floated basic button">
     Delete
   </div>
 </div>

</div>

The form is visible in the resulting page, with the correct id (as requested by th:id="${'edit-entry-modal-'+editEntryForm.id}"), so i assume the that my binding is correct.

But the template evaluation can't be completed, I have the following error


org.thymeleaf.exceptions.TemplateInputException: An error happened during template parsing (template: "class path resource [templates/timesheet/show.html]")
        at 
...
    Caused by: java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'editEntryForm' available as request attribute
...
2020-05-15 09:19:47.449 ERROR 10251 --- [nio-9090-exec-2] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.thymeleaf.exceptions.TemplateInputException: An error happened during template parsing (template: "class path resource [templates/timesheet/show.html]")] with root cause
...
java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'editEntryForm' available as request attribute
        at org.springframework.web.servlet.support.BindStatus.<init>(BindStatus.java:153) ~[spring-webmvc-5.2.6.RELEASE.jar:5.2.6.RELEASE]
        at 

Do you see something I'm doing wrong, or maybe it's a limitation of Thymleaf that I'm not aware of.

benzen
  • 6,204
  • 4
  • 25
  • 37
  • This is similar to https://stackoverflow.com/questions/59699927/getting-neither-bindingresult-nor-plain-target-object-for-bean-name-bean-name?rq=1 – benzen May 15 '20 at 13:44
  • And also this one https://stackoverflow.com/questions/53787332/how-to-bind-an-object-to-a-form-thobject-using-theach-for-a-list-of-objects – benzen May 15 '20 at 13:59
  • 1
    Yeah, you can't use the result of a `th:each` as your `th:object`. It has to be an object added directly to the model. Also, you can't use a `List` as your `th:object` either, it has to be a regular object. – Metroids May 15 '20 at 14:14
  • Is this something that could be adjusted in thymleaf, I mean should i raise an issue on their github ? – benzen May 15 '20 at 15:32

2 Answers2

0

Try using a plain Java Array, for iterating through in Thymeleaf in your th:each. Maybe try something like a .toArray() on editEntryForms since that should be of type List<>. Then delete your th:object in form. Now you should be able to access the contents of all the items in the Array, like you normally would in Thymeleaf. Also throw a look at my updated Answer to my question https://stackoverflow.com/a/59703725/10112957

C0D3 M4513R
  • 140
  • 1
  • 14
0

In my case what i ended up doing, is making a list of ids (ex. [1,2,3]) and adding a bunch of form to the model using the same id in the name (p.ex "form_1", "form_2", "form_3").

In the template, i iterate over the list of ids with a th:each="id : ${ids}" and my th:object looks like this

th:object="${__${'form_'+ id}__}"

This way the th:object bind to a value that is directly below the model and i iterate to access it

benzen
  • 6,204
  • 4
  • 25
  • 37