简体   繁体   中英

Editing a java arraylist in thymeleaf

The scenario:

Java + springboot + thymeleaf. I have a question entity which has a @OneToMany relationship with an answer entity:

@Entity
public class Question {

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "question_gen")
    @SequenceGenerator(name = "question_gen", sequenceName = "QUESTION_SEQ", allocationSize = 1)
    private long questionId;

    @Column
    private String questionText;

    @OneToMany(cascade =  CascadeType.PERSIST)
    @LazyCollection(LazyCollectionOption.FALSE)
    private List<Answer> answers = new ArrayList<>();

    @Column
    private String correctAnswer;

    @Column
    private boolean approved;

    @ManyToMany(cascade = CascadeType.PERSIST)
    @LazyCollection(LazyCollectionOption.FALSE)
    private List<Tag> tags;

    public Question(String questionText, List<Answer> answers, String correctAnswer, boolean approved) {
        super();
        this.questionText = questionText;
        this.answers = answers;
        this.correctAnswer = correctAnswer;
        this.approved = approved;
    }

    public Question(String questionText, List<Answer> answers, String correctAnswer, boolean approved, List<Tag> tags) {
        super();
        this.questionText = questionText;
        this.answers = answers;
        this.correctAnswer = correctAnswer;
        this.approved = approved;
        this.tags = tags;
    }

    public Question() {
        super();
    }

standard getter and setter etc follow

@Entity
public class Answer {

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "answer_gen")
    @SequenceGenerator(name = "answer_gen", sequenceName = "ANSWER_SEQ", allocationSize = 1)
    private long answerId;

    @Column
    private String answerText;

    public Answer(String answerText) {
        super();
        this.answerText = answerText;
    }

    public Answer() {
        super();
    }

The controller

@GetMapping("/EditQuestion/{questionId}")
    public ModelAndView editQuestion(@PathVariable("questionId") long questionId, ModelAndView modelAndView) {
        Optional<Question> question = questionService.retrieveOne(questionId);
        modelAndView.addObject("question", question.get());
        modelAndView.addObject("allTags", tagService.retrieveAll());
        modelAndView.addObject("answers", question.get().getAnswers());
        if (question.isPresent()) {
            modelAndView.setViewName("editQuestion");
            return modelAndView;
        }
        return modelAndView;
    }

    @PostMapping("/EditQuestionSubmit")
    public ModelAndView editQuestionSubmit(ModelAndView modelAndView, Question question) {
        if (questionService.update(question)) {
            modelAndView.addObject("allQuestions", questionService.retrieveAll());
            modelAndView.setViewName("allQuestions");
            return modelAndView;
        }
        modelAndView.setViewName("allQuestions");
        return modelAndView;
    }

listing, retrieving one and adding through a thymeleaf all working but when I try to edit the list just gets nulls

The thymeleaf:

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Edit Question Details</title>
</head>
<body>


    <h1>Edit Question Details</h1>


    <form action="#" th:action="@{/EditQuestionSubmit}"
        th:object="${question}" method="post">

        <div>
            <p>
                <label th:if="${questionText} == null"
                    th:text=" ' Edit your question'" /></label>
            </p>
            <p>
                <input type="text" th:field="*{questionText}" />
            </p>
        </div>

        <div>
            <p>
                <label th:text=" 'enter answers A-D for this question ' "></label>
            </p>
            <p>
                <input type="text" th:field="*{answers}" value="${answerId}" />
            </p>
        </div>
        <input type="text" th:each="answer : ${answers}" th:id="answerId" th:text="${answer.answerText}"
            th:value="${answer.answerId}" name="answers"  th:field="*{answers}" />
                         
                        
                        
                        

        </div>

        <div>
            <p>
                <label th:if="${correctAnswer} == null"
                    th:text="'Select the correct answer for this question'" /></label>
            </p>
            <p>
                <select id="correctAnswer" name="correctAnswer"
                    th:value="${question.correctAnswer}"
                    th:selected="${question.correctAnswer}">
                    <option value="A">A</option>
                    <option value="B">B</option>
                    <option value="C">C</option>
                    <option value="D">D</option>
                </select>
            </p>
        </div>

        <div>
            <p>
                <label>select relevant tags</label>
            <p>
                <select id="tagId" multiple name="tags"
                    th:selected="${question.tags}">
                    <option th:each="tag : ${allTags}" th:value="${tag.tagId}"
                        th:text="${tag.name}"></option>
                </select>
            </p>
        </div>

        <div>
            <p>
                <button type="submit">Edit Question</button>
            </p>
        </div>
        <input type="hidden" th:field="*{questionId}" value="${questionId}" />
        

    </form>
</body>
</html>

all other fields are working, I've tried a lot of different things but no joy, and input greatly appreciated

the solution is multi part. First I added a wrapper class

public class AnswerWrapper {

    private List<Answer> answers;

    public void addAnswer(Answer answer, Question question) {
        int index = (int) question.getQuestionId();
        answers = question.getAnswers();
        this.answers.add(index, answer);
    }

}

Then I updated the controller

@GetMapping("/EditQuestion/{questionId}")
    public ModelAndView editQuestion(@PathVariable("questionId") long questionId, ModelAndView modelAndView) {
        Optional<Question> question = questionService.retrieveOne(questionId);
        List<Answer> answers = question.get().getAnswers();
        AnswerWrapper answerWrapper = new AnswerWrapper();
        for (int i = 0  ; i >= answers.size(); i++) {
            Answer answer = answers.get(i);
            answer.setAnswerId(answer.getAnswerId());
            answerWrapper.addAnswer(answer, question.get());
        }
        
        modelAndView.addObject("question", question.get());
        modelAndView.addObject("allTags", tagService.retrieveAll());
        modelAndView.addObject("answers", question.get().getAnswers());
        if (question.isPresent()) {
            modelAndView.setViewName("editQuestion");
            return modelAndView;
        }
        return modelAndView;
    }

no changes needed for the PostMapping Then I updated the thymeleaf

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Edit Question Details</title>
</head>
<body>


    <h1>Edit Question Details</h1>


    <form action="#" th:action="@{/EditQuestionSubmit}"
        th:object="${question}" method="post">

        <div>
            <p>
                <label th:if="${questionText} == null"
                    th:text=" ' Edit your question'" /></label>
            </p>
            <p>
                <input type="text" th:field="*{questionText}" />
            </p>
        </div>

        <div>
            <p>
                <label th:text=" 'enter answers A-D for this question ' "></label>
            </p>


            <div th:each="answer, answerIndex: *{answers}">
                <td><input
                    th:field="*{answers[__${answerIndex.index}__].answerText}"
                    th:value="${answer.getAnswerId()}" /></td> <input hidden
                    th:name="|answers[${answerIndex.index}].answerId|"
                    th:value="${answer.getAnswerId()}" />
            </div>


            <div>
                <p>
                    <label th:if="${correctAnswer} == null"
                        th:text="'Select the correct answer for this question'" /></label>
                </p>
                <p>
                    <select id="correctAnswer" name="correctAnswer"
                        th:value="${question.correctAnswer}"
                        th:selected="${question.correctAnswer}">
                        <option value="A">A</option>
                        <option value="B">B</option>
                        <option value="C">C</option>
                        <option value="D">D</option>
                    </select>
                </p>
            </div>

            <div>
                <p>
                    <label>select relevant tags</label>
                <p>
                    <select id="tagId" multiple name="tags"
                        th:selected="${question.tags}">
                        <option th:each="tag : ${allTags}" th:value="${tag.tagId}"
                            th:text="${tag.name}"></option>
                    </select>
                </p>
            </div>

            <div>
                <p>
                    <button type="submit">Edit Question</button>
                </p>
            </div>

            <input type="hidden" th:field="*{questionId}" value="${questionId}" />
    </form>
</body>
</html>

and now all is well

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM