Динамическая форма и привязка данных с помощью Spring MVC

В моем приложении Spring MVC мне нужно реализовать динамическую форму анкеты: у меня есть N вопросов, и для каждого у меня есть 3 варианта.

Итак, на моей странице у меня будет что-то вроде этого:

|    Question 1   |   1   |   2   |   3   |
|    Question 2   |   1   |   2   |   3   |
|    Question 3   |   1   |   2   |   3   |
|    ...          |   1   |   2   |   3   |
|    Question N   |   1   |   2   |   3   |

Вопросы хранятся в базе данных, и для вариантов я буду использовать переключатели. Я буду использовать тег forEach для создания динамических строк, но я не знаю, как публиковать данные и обрабатывать привязку ModelAttribute в этом сценарии...

Что может быть хорошей структурой для моего класса атрибутов модели? Можно ли использовать привязку для динамической формы с помощью Spring MVC?


person davioooh    schedule 24.04.2014    source источник
comment
Автозаполнение списка   -  person GriffeyDog    schedule 24.04.2014
comment
Я бы просто создал класс POJO для вопроса, а атрибутом моей модели был бы простой список этих объектов вопроса, простой и удобный в обращении ---- myList‹Question› (или ну, если вам просто нужен текст вопроса и ответ, вы можете просто использовать список массивов или карт)   -  person Enoque Duarte    schedule 24.04.2014


Ответы (2)


как публиковать данные и обрабатывать привязку ModelAttribute в этом сценарии

ты можешь сделать,

я рассматриваю класс Question, например:

public class Question {
    private String question;
    private Map<Integer,Option> optionMap;
    private Integer selectedOptionKey;
        //getters and setters
}

и Option класс, например:

public class Option {

    private Integer optionKey;
    private String optionText;

    //getters and setters
}

и один класс QuestionsModel для привязки формы, например:

public class QuestionsModel {
    private Map<Integer, Question> questionMap;
    //getters and setters
}

и внутри метода обработчика GET класса контроллера заполните вопросы, например:

@RequestMapping(method=RequestMethod.GET)
    public String index(Model model){                
    Option optionA = new Option(1, "A");
    Option optionB = new Option(2, "B");
    Option optionC = new Option(3, "C");

    Map<Integer, Option> optionMap = new HashMap<Integer, Option>();
    optionMap.put(optionA.getOptionKey(),optionA);
    optionMap.put(optionB.getOptionKey(),optionB);
    optionMap.put(optionC.getOptionKey(),optionC);

    Question question1 = new Question("A Q", optionMap, 1);
    Question question2 = new Question("B Q", optionMap, 1);
    Question question3 = new Question("C Q", optionMap, 1);
    Map<Integer, Question> questionMap = new HashMap<Integer, Question>();
    questionMap.put(1, question1);
    questionMap.put(2, question2);
    questionMap.put(3, question3);

    model.addAttribute("questionsModel", new QuestionsModel(questionMap));

    return "index";
}

наконец, на странице jsp используйте <form:hidden.. для сохранения старых значений и отображения элементов формы, таких как:

<c:url value="/questionPost" var="postUrl"/>

<form:form action="${postUrl}" modelAttribute="questionsModel" method="post">
    <table>
    <tr>
        <th>Question</th>
        <th>Options</th>        
    </tr>   
    <c:forEach items="${questionsModel.questionMap}" var="currQue" varStatus="queIndex">
        <tr>
            <td>
                <form:hidden path="questionMap[${queIndex.count}].question"/>
                <label>Question:</label><c:out value="${currQue.value.question}"/><br/>
            </td>
            <td>
            <c:forEach items="${currQue.value.optionMap}" var="opt" varStatus="optionIndex">
                <form:hidden path="questionMap[${queIndex.count}].optionMap[${optionIndex.count}].optionText"/>
                <form:hidden path="questionMap[${queIndex.count}].optionMap[${optionIndex.count}].optionKey"/>

                <form:radiobutton path="questionMap[${queIndex.count}].selectedOptionKey"
                    value="${opt.value.optionKey}" label="${opt.value.optionText}"/>

            </c:forEach>

             </td>
        </tr>
    </c:forEach>
    </table>
    <input type="submit"/>
</form:form>

вы можете получить привязку и модель в POST, например:

@RequestMapping(value="/questionPost", method=RequestMethod.POST)
public String indexPost(@ModelAttribute("questionsModel") QuestionsModel questionModel, BindingResult result){
    System.out.println(questionModel.getQuestionMap());

    return "redirect:/";
} 
person Abhishek Nayak    schedule 25.04.2014

Этот класс является моим атрибутом модели:

public class Questionnaire {
    private List<Question> questions = new ArrayList<>();
    private List<Answer> answers = new ArrayList<>();

    // set + get
}

И:

public class Question {
    private int id;
    private String text;

    // set+ get

}

public class Answer {
    private int questionId;
    private int value;

    // set + get
}

Я заполняю список questions перед тем, как поместить его в модель.

На моей странице я использую этот код:

<c:forEach items="${questionnaire.questions}" var="question"
    varStatus="gridRow">
    <div>
    ${question.text} 
        <s:bind path="questionnaire.answers[${gridRow.index}].questionID">
            <input type="hidden" name="${status.expression}"
                id="${status.expression}" value="${question.id}" />
        </s:bind>
        <s:bind path="questionnaire.answers[${gridRow.index}].value">
            <sf:radiobuttons path="${status.expression}"
                items="${radio_button_options}" />
        </s:bind>
    </div>
</c:forEach>

Отправляя эту форму, я получаю полностью заполненный экземпляр questionnaire в своем контроллере.

ПРИМЕЧАНИЕ Я нашел этот пост очень полезным для решения моя проблема.

person davioooh    schedule 28.04.2014
comment
Ссылка, которую я нашел в этом посте очень полезной, не работает. - person Kimball Robinson; 23.02.2016