2017-03-14 65 views
0

我有以下型號(不getter和setter可讀性):如何填寫Thymeleaf中多個對象的一個​​表單中的字段?

@Entity 
public class Recipe extends BaseEntity { 
    private String name; 
    private String description; 
    private Category category; 

    @OneToMany(mappedBy = "recipe", cascade = CascadeType.ALL) 
    private List<Ingredient> ingredients; 

    @OneToMany(mappedBy = "recipe", cascade = CascadeType.ALL) 
    private List<Instruction> instructions; 

    @ManyToMany 
    private List<User> administrators; 

    private int preparationTime; 
    private int cookTime; 

    public Recipe(){ 
    super(); 
    ingredients = new ArrayList<>(); 
    instructions = new ArrayList<>(); 
    administrators = new ArrayList<>(); 
    } 

    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; 
    } 

*

@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; 
    } 

*

@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; 
    } 

什麼,我需要做的是填寫字段每個對象放在一個Thymeleaf窗體中並POST。我知道如何用單個對象來做到這一點。請解釋如何設置多個對象的from和控制器,所以最後生病的食譜貼有配料和說明列表。謝謝!

編輯: 這裏是一個控制器方法:

 @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(); 
    } 

和Thymeleaf形式:

<form th:action="@{${action}}" method="post" th:object="${recipe}"> 

       <div class="grid-100 row controls"> 
        <div class="grid-50"> 
         <h2 th:text="${heading}"></h2> 
        </div> 
        <div class="grid-50"> 
         <div class="flush-right"> 
          <input class="button" type="submit" th:value="${submit}"/> 
          <a th:href="@{|/recipes|}" class="secondary"> 
           <button class="secondary">Cancel</button> 
          </a> 
         </div> 
        </div> 
       </div> 
       <div class="clear"></div> 

       <div class="grid-100 row"> 
        <div class="grid-20"> 
         <p class="label-spacing"> 
          <label> Name </label> 
         </p> 
        </div> 
        <div class="grid-40"> 
         <p><input type="text" th:field="*{name}"/> 
         <div class="error-message" 
          th:if="${#fields.hasErrors('name')}" 
          th:errors="*{recipe.name}"> 
         </div> 
         </p> 
        </div> 
       </div> 
       <div class="clear"></div> 

       <div class="grid-100 row"> 
        <div class="grid-20"> 
         <p class="label-spacing"> 
          <label> Description </label> 
         </p> 
        </div> 
        <div class="grid-40"> 
         <p><textarea rows="4" th:field="*{description}"></textarea> 
         <div class="error-message" 
          th:if="${#fields.hasErrors('description')}" 
          th:errors="*{recipe.description}"> 
         </div> 
         </p> 
        </div> 
       </div> 
       <div class="clear"></div> 

       <div class="grid-100 row"> 
        <div class="grid-20"> 
         <p class="label-spacing"> 
          <label> Category </label> 
         </p> 
        </div> 
        <div class="grid-30"> 
         <p> 
          <select th:field="*{category}"> 
           <option value="" disabled="disabled">Recipe Category</option> 
           <option th:each="c : ${categories}" 
             th:value="${c.name}" 
             th:text="${c.name}">All Categories</option> 
          </select> 
         </p> 
        </div> 
       </div> 
       <div class="clear"></div> 

       <div class="grid-100 row"> 
        <div class="grid-20"> 
         <p class="label-spacing"> 
          <label> Prep Time </label> 
         </p> 
        </div> 
        <div class="grid-20"> 
         <p> 
          <input type="number" th:field="*{preparationTime}"/> 
         <div class="error-message" 
          th:if="${#fields.hasErrors('preparationTime')}" 
          th:errors="*{preparationTime}"></div> 
         </p> 
        </div> 
       </div> 
       <div class="clear"></div> 

       <div class="grid-100 row"> 
        <div class="grid-20"> 
         <p class="label-spacing"> 
          <label> Cook Time </label> 
         </p> 
        </div> 
        <div class="grid-20"> 
         <p> 
          <input type="number" th:field="*{cookTime}"/> 
         <div class="error-message" 
          th:if="${#fields.hasErrors('cookTime')}" 
          th:errors="*{cookTime}"></div> 
         </p> 
        </div> 
       </div> 
       <div class="clear"></div> 

       <div class="grid-100 row"> 
        <div class="grid-20"> 
         <p class="label-spacing"> 
          <label> Ingredients </label> 
         </p> 
        </div> 
        <div class="grid-20"> 
         <p class="label-spacing"> 
          <label> Item </label> 
         </p> 
        </div> 
        <div class="grid-20"> 
         <p class="label-spacing"> 
          <label> Condition </label> 
         </p> 
        </div> 
        <div class="grid-15"> 
         <p class="label-spacing"> 
          <label> Quantity </label> 
         </p> 
        </div> 
        <div class="grid-20"> 
         <p class="label-spacing"> 
          <label> Measurement </label> 
         </p> 
        </div> 

        <div class="ingredient-row"> 
         <div class="prefix-20 grid-20"> 
          <p> 
           <input type="text" th:field="*{ingredients[0].name}"/> 
          <div class="error-message" 
           th:if="${#fields.hasErrors('ingredients[0].name')}" 
           th:errors="*{ingredients[0].name}"></div> 
          </p> 
         </div> 
         <div class="grid-20"> 
          <p> 
           <input type="text" th:field="*{ingredients[0].condition}"/> 
          <div class="error-message" 
           th:if="${#fields.hasErrors('ingredients[0].condition')}" 
           th:errors="*{ingredients[0].condition}"></div> 
          </p> 
         </div> 
         <div class="grid-15"> 
          <p> 
           <input type="number" th:field="*{ingredients[0].quantity}"/> 
          <div class="error-message" 
           th:if="${#fields.hasErrors('ingredients[0].quantity')}" 
           th:errors="*{ingredients[0].quantity}"></div> 
          </p> 
         </div> 
         <div class="grid-20"> 
          <p> 
           <select th:field="*{ingredients[0].measurement}"> 
            <option value="" disabled="disabled">Measurement</option> 
            <option th:each="i : ${measurements}" 
              th:value="${i.name}" 
              th:text="${i.name}">Unknown 
            </option> 
           </select> 
          </p> 
         </div> 
        </div> 

        <div class="prefix-20 grid-80 add-row"> 
         <p> 
          <button>+ Add Another Ingredient</button> 
         </p> 
        </div> 

       </div> 
       <div class="clear"></div> 

       <div class="grid-100 row"> 
        <div class="grid-20"> 
         <p class="label-spacing"> 
          <label> Instructions </label> 
         </p> 
        </div> 
        <div class="grid-20"> 
         <p class="label-spacing"> 
          <label> Steps </label> 
         </p> 
        </div> 
        <div class="grid-60"> 
         <p class="label-spacing"> 
          <label> Description </label> 
         </p> 
        </div> 

        <div class="instruction-row"> 
         <div class="prefix-20 grid-20"> 
          <p> 
           <input type="text" th:field="*{instructions[0].name}"/> 
          <div class="error-message" 
           th:if="${#fields.hasErrors('instructions[0].name')}" 
           th:errors="*{instructions[0].name}"></div> 
          </p> 
         </div> 
        </div> 

        <div class="instruction-row"> 
         <div class="grid-50"> 
          <p> 
           <input type="text" th:field="*{instructions[0].description}"/> 
          <div class="error-message" 
           th:if="${#fields.hasErrors('instructions[0].description')}" 
           th:errors="*{instructions[0].description}"></div> 
          </p> 
         </div> 
        </div> 

        <div class="prefix-20 grid-80 add-row"> 
         <p> 
          <button>+ Add Another Step</button> 
         </p> 
        </div> 

       </div> 
       <div class="clear"></div> 

       <div class="row">&nbsp;</div> 
      </form> 

回答

2

它看起來是這樣的:

<form th:object="${recipe}"> 
    <input type="text" th:field="*{ingredients[0].name}" /> 
    <input type="text" th:field="*{ingredients[1].name}" /> 

    <input type="text" th:field="*{instructions[0].name}" /> 
    <input type="text" th:field="*{instructions[0].description}" /> 
</form> 

如果你有一個動態的量的配料,th:each可能看起來像這樣:

<th:block th:each="ingredient,i : ${recipe.ingredients}"> 
    <input type="text" th:field="*{ingredients[__${i.index}__].name}" /><br /> 
    <input type="text" th:field="*{ingredients[__${i.index}__].condition}" /><br /> 
    <input type="text" th:field="*{ingredients[__${i.index}__].quantity}" /><br /> 
    <input type="text" th:field="*{ingredients[__${i.index}__].measurement.anotherField}" /><br /> 
</th:block> 

動態添加其他成分的形式是一種痛苦......你要麼必須提交表單和修改配方對象在控制器(添加的成分,然後重定向回的形式)。或者,您可以使用JavaScript來複制字段,確保名稱/ ID/etc與其他字符匹配,且索引遞增。

+0

我已經嘗試創建並填寫表單以單一成分和單個指令開始。當我提交表單時,只有名稱,說明,類別,準備時間,cookTime等食譜字段得到保存。這兩個成分和步驟清單仍然是空的.. –

+0

忘記設置控制器中每種成分的配方。 recipe.getIngredients()。forEach(ingredient - > ingredient.setRecipe(recipe)); 現在一切正常。謝謝! –

相關問題