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で動的フォームのバインディングを使用することは可能ですか?
このシナリオでデータを投稿して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
}
そして、次のようなフォームバインディング用の1つの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:/";
}
このクラスは私のモデル属性です:
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
インスタンスが表示されます。
[〜#〜] note [〜#〜]私は この投稿 私の問題を解決するのに非常に役立ちました。