dynamic form with springmvc and thymeleaf

Requirements

SubjectGroup and SubjectGroupOption has one-to-many relationship. When adding a subject group, subject group options can be added inline.

Things I’ve learned.

Code

SubjectGroupController.java

package edc.web;

import edc.model.SubjectGroup;
import edc.model.SubjectGroupOption;
import edc.service.SubjectGroupService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
@RequestMapping("/sg")
public class SubjectGroupController {
    private SubjectGroupService subjectGroupService;

    @Autowired
    public void setSubjectGroupService(SubjectGroupService subjectGroupService) {
        this.subjectGroupService = subjectGroupService;
    }

    @RequestMapping(value = "add")
    public String add(SubjectGroup subjectGroup) {
        return "subjectGroup/add";
    }

    @RequestMapping(value = "add", params = {"addOption"})
    public String addOption(SubjectGroup subjectGroup, BindingResult result) {
        subjectGroup.getOptions().add(new SubjectGroupOption());
        return "subjectGroup/add";
    }

    @RequestMapping(value = "add", method = RequestMethod.POST)
    public String save(SubjectGroup subjectGroup, BindingResult result) {
        this.subjectGroupService.save(subjectGroup);
        return "redirect:/sg/add";
    }
}

add.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="utf-8"/>
    <title></title>
</head>
<body>
<section>
    <h2>Add Subject Group</h2>
    <form action="#" th:action="@{/sg/add}" th:object="${subjectGroup}" method="POST">
      <p><input type="text" th:field="*{name}" placeholder="Name..."/></p>
        <h3>Options</h3>
        <button type="submit" name="addOption">Add Option</button>
        <table>
            <tr th:each="option, rowStat : *{options}">
              <td><input type="text" th:field="*{options[__${rowStat.index}__].label}" placeholder="Option..."/></td>
            </tr>
        </table>
        <button type="submit">Add</button>
    </form>
</section>
</body>
</html>