Spring 4 MVC表单:使用子对象列表创建对象

时间:2017-01-25 20:59:04

标签: spring spring-mvc spring-data

我正在寻求帮助,了解如何通过一个表单来创建一个新对象,该表单允许用户选择多个子对象(这些子对象将被预先填充)并可以通过复选框进行选择。

OrderController.java

@RequestMapping(value = { "/order" }, method = RequestMethod.GET)
public String order(ModelMap model) {

    List<Exam> exams = examService.findAllExams();
    List<Document> documents = documentService.findAllDocuments();

    model.addAttribute("exams", exams);
    model.addAttribute("documents", documents);

    return "order"; // jsp page reference
}

Order.java

@Entity
@Table(name="\"order\"")
    public class Order implements Serializable
    {
        private static final long serialVersionUID = 1L;

        @Id 
        @GeneratedValue(strategy=GenerationType.IDENTITY)
        @Column(name = "order_id", unique = true, nullable = false)
        private Integer id;

        @GeneratedValue(generator = "uuid")
        @GenericGenerator(name = "uuid", strategy = "uuid2")
        @Column(name = "uuid", unique = true, nullable = false)
        private String uuid;

        @Temporal(TemporalType.DATE)
        @Column(name = "order_date", unique = true, nullable = false)
        private Date orderDate;

        @Column(name="order_status", nullable=false)
        private String orderStatus;

        @ManyToOne(fetch = FetchType.LAZY)
        @JoinColumn(name = "user_id", nullable = false)
        private User user;

        @OneToMany(fetch = FetchType.LAZY, mappedBy = "order")
        private Set<OrderExam> orderExams = new HashSet<OrderExam>(0);

        @OneToMany(fetch = FetchType.LAZY, mappedBy = "order")
        private Set<OrderDocument> orderDocuments = new HashSet<OrderDocument(0); 

        //getters & setters
    }

OrderExam.java

@Entity
@Table(name="order_exam")
public class OrderExam implements Serializable
{
    private static final long serialVersionUID = 1L;

    @Id 
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    @Column(name = "order_exam_id", unique = true, nullable = false)
    private Integer id;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "order_id", nullable = false)
    private Order order;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "exam_id", nullable = false)
    private Exam exam;

    @Column(name="exam_amount", nullable=true)
    private Integer examAmount;

    @Column(name="answer_sheet_amount", nullable=true)
    private String answerSheetName;

    @Column(name="students_per_csv", nullable=true)
    private String studentsPerCSV;

    @Column(name="pas", nullable=true)
    private Boolean pearsonAnswerSheet;

    //getters & setters
}

Exam.java

@Entity
@Table(name="exam")
public class Exam implements Serializable
{
    private static final long serialVersionUID = 1L;

    @Id 
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    @Column(name = "exam_id", unique = true, nullable = false)
    private Integer id;

    @NotEmpty
    @Column(name="name", unique=true, nullable=false)
    private String name;

    @NotEmpty
    @Column(name="code", unique=true, nullable=false)
    private String code;

    @OneToMany(fetch = FetchType.LAZY, mappedBy = "exam")
    private Set<OrderExam> exams = new HashSet<OrderExam>(0);

     //getters & setters
}

正如您所看到的,我传递的考试和文档列表将填充带有可用选项的表单(可以在下图中看到(考试))。用户需要能够选择多行,以便单个订单具有多个与之关联的考试和文档。

OrderForm:Exams

我的order.jsp在这里发布的内容有点多,但这里是上面图片中显示的部分。

Order.jsp

<form:form method="POST" modelAttribute="order" class="form-horizontal form-label-left">
<c:forEach items="${exams}" var="exam">
                                                <tr>
                                                    <th scope="row"><input type="checkbox" class="flat"></th>
                                                    <td><input id="middle-name" type="text" name="middle-name" readonly="readonly" value="${exam.name} - ${exam.code}" class="form-control col-md-7 col-xs-12"></td>
                                                    <td><input id="middle-name" type="text" name="middle-name" value="0" class="form-control col-md-3 col-xs-12"></td>
                                                    <td><input id="middle-name" type="text" name="middle-name" value="0" class="form-control col-md-3 col-xs-12"></td>
                                                    <td><input id="middle-name" type="text" name="middle-name" value="0" class="form-control col-md-3 col-xs-12"></td>
                                                    <c:choose>
                                                        <c:when test="${exam.name == 'Algebra 2 (Common Core)'}">
                                                            <th scope="row"><input type="checkbox" class="flat"></th>
                                                        </c:when>
                                                        <c:otherwise>
                                                            <th scope="row"></th>
                                                        </c:otherwise>
                                                    </c:choose>
                                                </tr>
                                            </c:forEach>
<!-- Other Stuff Goes Here -->
</form:form>

简而言之,有人愿意告诉我如何以上述方式设置表单吗?提前谢谢。

1 个答案:

答案 0 :(得分:1)

您的问题有点宽泛,但您可以尝试以下方式。我只参加了考试。文件的负责人将是相同的。

您需要几个新类来捕获提交的表单输入:

订购表单以捕获选择

public class OrderForm{

    private List<ExamWrapper> allAvailableExams = new ArrayList<>();

    private XOptionPrintWrapper selectedWrapper;

    public OrderForm(){

    }

    //getters and setters
}

考试包装:用选择的&#39;来装饰考试。属性

public class ExamWrapper{

    private boolean selected;
    private Exam exam;

    public ExamWrapper(Exam exam){
        this.exam = exams;
    }

    //getters and setters
}

将控制器更改为

public class OrderController{

    //Exams model populated by the method below
    //moved as we also need it populated on POST
    @RequestMapping(value = { "/order" }, method = RequestMethod.GET)
    public String order(ModelMap modelMap) {

        //only needed on GET so put in model here
        List<XOptionPrintWrapper> availableWrappers = //someList;
        modelMap.put("availableWrappers", availableWrappers);

        return "order"; 
    }

    //handles for submit
    //model atribute is automatically populated by the framework
    @RequestMapping(value = { "/order" }, method = RequestMethod.POST)
    public String order(@ModelAttribute("orderForm") OrderForm orderForm) {

        //process selected exams

        return "nextView"; 
    }

    //on get populates the initial model for display
    //on post create an instance which the form params will be bound to
    @ModelAttribute("orderForm")
    public OrderForm getOrderForm(){
        OrderForm orderForm = new OrderForm();
        List<Exam> exams = examService.findAllExams();

        for(Exam exam : exams){
            orderForm.getAllAvailableExams.add(new ExamWrapper(exam));
        }

        return orderForm;
    }
}

在JSP中使用Sping支持绑定到索引属性:

<form:form method="POST" modelAttribute="orderForm" class="form-horizontal form-label-left">
    <c:forEach items="${orderForm.allAvailableExams}" var="exam" varStatus="status">
        <tr>
            <th scope="row"><input name="allAvailableExams[${status.index}].selected" 
                     type="checkbox" class="flat"></th>
        </tr>
    </c:forEach>

        <form:select path="selectedWrapper">
        <form:options items="${availableWrappers}" 
               itemValue="somePropertyOfXOptionPrintWrapper " 
               itemLabel="somePropertyOfXOptionPrintWrapper " />
        </form:select>
</form>

我显然无法尝试所有这些,但认为一切都会好起来的。