Pregunta Forma dinámica y enlace de datos con Spring MVC


En mi aplicación Spring MVC necesito implementar un cuestionario dinámico: tengo N preguntas y para cada una tengo 3 opciones.

Entonces en mi página tendré algo como esto:

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

Las preguntas se almacenan en una base de datos y para las opciones usaré botones de opción. Usaré un forEach etiqueta para crear filas dinámicas, pero no sé cómo publicar datos y manejar ModelAttribute vinculante en este escenario ...

¿Cuál podría ser una buena estructura para mi clase de atributo de modelo? ¿Es posible usar el enlace para una forma dinámica con Spring MVC?


8
2018-04-24 15:07


origen


Respuestas:


cómo publicar datos y manejar el enlace de ModelAttribute en este escenario

tu puedes hacer,

estoy considerando Question Clase como:

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

y Option Clase como:

public class Option {

    private Integer optionKey;
    private String optionText;

    //getters and setters
}

y uno QuestionsModel clase para enlace de formulario como:

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

y dentro de la clase de controlador GET método del controlador, rellenar preguntas por ejemplo:

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

finalmente en el uso de la página jsp <form:hidden.. para mantener valores antiguos y representar elementos de formulario como:

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

puede recibir vinculante y modelo en POST como:

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

    return "redirect:/";
} 

12
2018-04-25 13:41



Esta clase es mi atributo del modelo:

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

    // set + get
}

Y:

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

    // set+ get

}

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

    // set + get
}

Yo puebla questions lista antes de ponerlo en el modelo.

En mi página uso este código:

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

Publicando esta forma obtengo una población completa questionnaire instancia en mi controlador.

NOTA encontré esta publicación muy útil para resolver mi problema.


2
2018-04-28 16:27