title: How to fill out fields in one form for multiple objects in Thymeleaf?
body: <p>I have a following models (without getters and setters for readability): </p>
  
  <pre><code>   @Entity
  public class Recipe extends BaseEntity {
    private String name;
    private String description;
    private Category category;
  
    @OneToMany(mappedBy = "recipe", cascade = CascadeType.ALL)
    private List&lt;Ingredient&gt; ingredients;
  
    @OneToMany(mappedBy = "recipe", cascade = CascadeType.ALL)
    private List&lt;Instruction&gt; instructions;
  
    @ManyToMany
    private List&lt;User&gt; administrators;
  
    private int preparationTime;
    private int cookTime;
  
    public Recipe(){
      super();
      ingredients = new ArrayList&lt;&gt;();
      instructions = new ArrayList&lt;&gt;();
      administrators = new ArrayList&lt;&gt;();
    }
  
    public Recipe(String name, String description, Category category, int preparationTime, int cookTime) {
      this();
      this.name = name;
      this.description = description;
      this.category = category;
      this.preparationTime = preparationTime;
      this.cookTime = cookTime;
    }
  </code></pre>
  
  <p>*</p>
  
  <pre><code>@Entity
  public class Ingredient extends BaseEntity {
    private String name;
    private String condition;
    private double quantity;
    private Measurement measurement;
  
    @ManyToOne
    private Recipe recipe;
  
    public Ingredient(){
      super();
    }
  
    public Ingredient(String name, String condition, double quantity, Measurement measurement) {
      this();
      this.name = name;
      this.condition = condition;
      this.quantity = quantity;
      this.measurement = measurement;
    }
  </code></pre>
  
  <p>*</p>
  
  <pre><code>@Entity
  public class Instruction extends BaseEntity {
    private String name;
    private String description;
  
    @ManyToOne
    private Recipe recipe;
  
    public Instruction(){
      super();
    }
  
    public Instruction(String name, String description) {
      this();
      this.name = name;
      this.description = description;
    }
  </code></pre>
  
  <p>What i need to do is to fill out fields for each object in one Thymeleaf form and POST it. I know how to do it with a single object. Please explain how to set up the from and controller for multiple objects, so in the end ill have recipe posted with ingredients and instructions list. Thanks!     </p>
  
  <p>EDITED:
  Here is a controller methods:</p>
  
  <pre><code>     @RequestMapping("/recipes/add")
    public String formNewRecipe(Model model) {
      Recipe recipe = new Recipe();
  
      if (!model.containsAttribute("recipe")) {
        model.addAttribute("recipe", recipe);
      }
      model.addAttribute("action", "/recipes");
      model.addAttribute("heading", "New Recipe");
      model.addAttribute("submit", "Save");
      model.addAttribute("categories", Category.values());
      model.addAttribute("measurements", Measurement.values());
      return "edit";
    }
  
    @RequestMapping(value = "/recipes", method = RequestMethod.POST)
    public String addRecipe(@Valid Recipe recipe,
                            BindingResult result,
                            RedirectAttributes redirectAttributes) {
  
      if (result.hasErrors()) {
        redirectAttributes
            .addFlashAttribute("org.springframework.validation.BindingResult.recipe", result);
        redirectAttributes.addFlashAttribute("recipe", recipe);
        return "redirect:/recipes/add";
      }
  
      recipes.save(recipe);
      redirectAttributes.addFlashAttribute("flash",
          new FlashMessage("New Recipe Created!!!", FlashMessage.Status.SUCCESS));
      return "redirect:/recipes/" + recipe.getId();
    }
  </code></pre>
  
  <p>and Thymeleaf form:</p>
  
  <pre><code>&lt;form th:action="@{${action}}" method="post" th:object="${recipe}"&gt;
  
                  &lt;div class="grid-100 row controls"&gt;
                      &lt;div class="grid-50"&gt;
                          &lt;h2 th:text="${heading}"&gt;&lt;/h2&gt;
                      &lt;/div&gt;
                      &lt;div class="grid-50"&gt;
                          &lt;div class="flush-right"&gt;
                              &lt;input class="button" type="submit" th:value="${submit}"/&gt;
                              &lt;a th:href="@{|/recipes|}" class="secondary"&gt;
                                  &lt;button class="secondary"&gt;Cancel&lt;/button&gt;
                              &lt;/a&gt;
                          &lt;/div&gt;
                      &lt;/div&gt;
                  &lt;/div&gt;
                  &lt;div class="clear"&gt;&lt;/div&gt;
  
                  &lt;div class="grid-100 row"&gt;
                      &lt;div class="grid-20"&gt;
                          &lt;p class="label-spacing"&gt;
                              &lt;label&gt; Name &lt;/label&gt;
                          &lt;/p&gt;
                      &lt;/div&gt;
                      &lt;div class="grid-40"&gt;
                          &lt;p&gt;&lt;input type="text" th:field="*{name}"/&gt;
                          &lt;div class="error-message"
                               th:if="${#fields.hasErrors('name')}"
                               th:errors="*{recipe.name}"&gt;
                          &lt;/div&gt;
                          &lt;/p&gt;
                      &lt;/div&gt;
                  &lt;/div&gt;
                  &lt;div class="clear"&gt;&lt;/div&gt;
  
                  &lt;div class="grid-100 row"&gt;
                      &lt;div class="grid-20"&gt;
                          &lt;p class="label-spacing"&gt;
                              &lt;label&gt; Description &lt;/label&gt;
                          &lt;/p&gt;
                      &lt;/div&gt;
                      &lt;div class="grid-40"&gt;
                          &lt;p&gt;&lt;textarea rows="4" th:field="*{description}"&gt;&lt;/textarea&gt;
                          &lt;div class="error-message"
                               th:if="${#fields.hasErrors('description')}"
                               th:errors="*{recipe.description}"&gt;
                          &lt;/div&gt;
                          &lt;/p&gt;
                      &lt;/div&gt;
                  &lt;/div&gt;
                  &lt;div class="clear"&gt;&lt;/div&gt;
  
                  &lt;div class="grid-100 row"&gt;
                      &lt;div class="grid-20"&gt;
                          &lt;p class="label-spacing"&gt;
                              &lt;label&gt; Category &lt;/label&gt;
                          &lt;/p&gt;
                      &lt;/div&gt;
                      &lt;div class="grid-30"&gt;
                          &lt;p&gt;
                              &lt;select th:field="*{category}"&gt;
                                  &lt;option value="" disabled="disabled"&gt;Recipe Category&lt;/option&gt;
                                  &lt;option th:each="c : ${categories}"
                                          th:value="${c.name}"
                                          th:text="${c.name}"&gt;All Categories&lt;/option&gt;
                              &lt;/select&gt;
                          &lt;/p&gt;
                      &lt;/div&gt;
                  &lt;/div&gt;
                  &lt;div class="clear"&gt;&lt;/div&gt;
  
                  &lt;div class="grid-100 row"&gt;
                      &lt;div class="grid-20"&gt;
                          &lt;p class="label-spacing"&gt;
                              &lt;label&gt; Prep Time &lt;/label&gt;
                          &lt;/p&gt;
                      &lt;/div&gt;
                      &lt;div class="grid-20"&gt;
                          &lt;p&gt;
                              &lt;input type="number" th:field="*{preparationTime}"/&gt;
                          &lt;div class="error-message"
                               th:if="${#fields.hasErrors('preparationTime')}"
                               th:errors="*{preparationTime}"&gt;&lt;/div&gt;
                          &lt;/p&gt;
                      &lt;/div&gt;
                  &lt;/div&gt;
                  &lt;div class="clear"&gt;&lt;/div&gt;
  
                  &lt;div class="grid-100 row"&gt;
                      &lt;div class="grid-20"&gt;
                          &lt;p class="label-spacing"&gt;
                              &lt;label&gt; Cook Time &lt;/label&gt;
                          &lt;/p&gt;
                      &lt;/div&gt;
                      &lt;div class="grid-20"&gt;
                          &lt;p&gt;
                              &lt;input type="number" th:field="*{cookTime}"/&gt;
                          &lt;div class="error-message"
                               th:if="${#fields.hasErrors('cookTime')}"
                               th:errors="*{cookTime}"&gt;&lt;/div&gt;
                          &lt;/p&gt;
                      &lt;/div&gt;
                  &lt;/div&gt;
                  &lt;div class="clear"&gt;&lt;/div&gt;
  
                  &lt;div class="grid-100 row"&gt;
                      &lt;div class="grid-20"&gt;
                          &lt;p class="label-spacing"&gt;
                              &lt;label&gt; Ingredients &lt;/label&gt;
                          &lt;/p&gt;
                      &lt;/div&gt;
                      &lt;div class="grid-20"&gt;
                          &lt;p class="label-spacing"&gt;
                              &lt;label&gt; Item &lt;/label&gt;
                          &lt;/p&gt;
                      &lt;/div&gt;
                      &lt;div class="grid-20"&gt;
                          &lt;p class="label-spacing"&gt;
                              &lt;label&gt; Condition &lt;/label&gt;
                          &lt;/p&gt;
                      &lt;/div&gt;
                      &lt;div class="grid-15"&gt;
                          &lt;p class="label-spacing"&gt;
                              &lt;label&gt; Quantity &lt;/label&gt;
                          &lt;/p&gt;
                      &lt;/div&gt;
                      &lt;div class="grid-20"&gt;
                          &lt;p class="label-spacing"&gt;
                              &lt;label&gt; Measurement &lt;/label&gt;
                          &lt;/p&gt;
                      &lt;/div&gt;
  
                      &lt;div class="ingredient-row"&gt;
                          &lt;div class="prefix-20 grid-20"&gt;
                              &lt;p&gt;
                                  &lt;input type="text" th:field="*{ingredients[0].name}"/&gt;
                              &lt;div class="error-message"
                                   th:if="${#fields.hasErrors('ingredients[0].name')}"
                                   th:errors="*{ingredients[0].name}"&gt;&lt;/div&gt;
                              &lt;/p&gt;
                          &lt;/div&gt;
                          &lt;div class="grid-20"&gt;
                              &lt;p&gt;
                                  &lt;input type="text" th:field="*{ingredients[0].condition}"/&gt;
                              &lt;div class="error-message"
                                   th:if="${#fields.hasErrors('ingredients[0].condition')}"
                                   th:errors="*{ingredients[0].condition}"&gt;&lt;/div&gt;
                              &lt;/p&gt;
                          &lt;/div&gt;
                          &lt;div class="grid-15"&gt;
                              &lt;p&gt;
                                  &lt;input type="number" th:field="*{ingredients[0].quantity}"/&gt;
                              &lt;div class="error-message"
                                   th:if="${#fields.hasErrors('ingredients[0].quantity')}"
                                   th:errors="*{ingredients[0].quantity}"&gt;&lt;/div&gt;
                              &lt;/p&gt;
                          &lt;/div&gt;
                          &lt;div class="grid-20"&gt;
                              &lt;p&gt;
                                  &lt;select th:field="*{ingredients[0].measurement}"&gt;
                                      &lt;option value="" disabled="disabled"&gt;Measurement&lt;/option&gt;
                                      &lt;option th:each="i : ${measurements}"
                                              th:value="${i.name}"
                                              th:text="${i.name}"&gt;Unknown
                                      &lt;/option&gt;
                                  &lt;/select&gt;
                              &lt;/p&gt;
                          &lt;/div&gt;
                      &lt;/div&gt;
  
                      &lt;div class="prefix-20 grid-80 add-row"&gt;
                          &lt;p&gt;
                              &lt;button&gt;+ Add Another Ingredient&lt;/button&gt;
                          &lt;/p&gt;
                      &lt;/div&gt;
  
                  &lt;/div&gt;
                  &lt;div class="clear"&gt;&lt;/div&gt;
  
                  &lt;div class="grid-100 row"&gt;
                      &lt;div class="grid-20"&gt;
                          &lt;p class="label-spacing"&gt;
                              &lt;label&gt; Instructions &lt;/label&gt;
                          &lt;/p&gt;
                      &lt;/div&gt;
                      &lt;div class="grid-20"&gt;
                          &lt;p class="label-spacing"&gt;
                              &lt;label&gt; Steps &lt;/label&gt;
                          &lt;/p&gt;
                      &lt;/div&gt;
                      &lt;div class="grid-60"&gt;
                          &lt;p class="label-spacing"&gt;
                              &lt;label&gt; Description &lt;/label&gt;
                          &lt;/p&gt;
                      &lt;/div&gt;
  
                      &lt;div class="instruction-row"&gt;
                          &lt;div class="prefix-20 grid-20"&gt;
                              &lt;p&gt;
                                  &lt;input type="text" th:field="*{instructions[0].name}"/&gt;
                              &lt;div class="error-message"
                                   th:if="${#fields.hasErrors('instructions[0].name')}"
                                   th:errors="*{instructions[0].name}"&gt;&lt;/div&gt;
                              &lt;/p&gt;
                          &lt;/div&gt;
                      &lt;/div&gt;
  
                      &lt;div class="instruction-row"&gt;
                          &lt;div class="grid-50"&gt;
                              &lt;p&gt;
                                  &lt;input type="text" th:field="*{instructions[0].description}"/&gt;
                              &lt;div class="error-message"
                                   th:if="${#fields.hasErrors('instructions[0].description')}"
                                   th:errors="*{instructions[0].description}"&gt;&lt;/div&gt;
                              &lt;/p&gt;
                          &lt;/div&gt;
                      &lt;/div&gt;
  
                      &lt;div class="prefix-20 grid-80 add-row"&gt;
                          &lt;p&gt;
                              &lt;button&gt;+ Add Another Step&lt;/button&gt;
                          &lt;/p&gt;
                      &lt;/div&gt;
  
                  &lt;/div&gt;
                  &lt;div class="clear"&gt;&lt;/div&gt;
  
                  &lt;div class="row"&gt;&amp;nbsp;&lt;/div&gt;
              &lt;/form&gt;
  </code></pre>