0

先生が質問をするフォームを作っています。質問の1つのタイプは、多肢選択式の質問です。フォームには、質問の定式化を記述するtextAreaと、選択肢のtextFieldsを含むlistViewがあります。

新しい選択肢を追加する(新しいtextFieldを追加する)ボタンがあり、押すとすべての選択肢が再描画され、新しい選択肢が追加されます。ここで問題があります:テキストを含むlistViewにすでにあるテキストフィールドに、再描画後に教師が書いたテキストを保持させたいのですが、これを可能にする方法がわかりません(再描画の前に値をデータベースに保存することを除いて) 、しかしそれは悪い考えのようです)。

これが私のMultipleChoiceQuestionPanelのコードです。それで十分だと思います。

public class MultiChoiceQuestionPanel extends QuestionPanel {

    private List<Alternative> alternatives;

    @SpringBean
    private AlternativeRepository alternativeRepository;

    public List<Alternative> getAlternatives(){
        return alternatives;
    }

    public MultiChoiceQuestionPanel(String id, MultipleChoiceQuestion q){
        super(id, q);

        final WebMarkupContainer parent = new WebMarkupContainer("alternativesContainer");
        parent.setOutputMarkupId(true);
        add(parent);
        parent.add(new Label("AnswerLabel", "Svar"));

        q.setAlternatives(alternativeRepository.findByMultipleChoiceQuestion(q));
        alternatives = q.getAlternatives();
        Form form = new Form("addForm");
        form.add(new ListView<Alternative>("alternatives", alternatives) {
            @Override
            protected void populateItem(final ListItem<Alternative> alternativeListItem) {
                alternativeListItem.add((TextField<String>) new TextField<String>("alternative", new AlternativeModel(alternativeListItem.getModelObject())).setRequired(true).setType(String.class));
                Form form = new Form("removeForm");
                form.add(new AjaxSubmitLink("remove") {
                    @Override
                    protected void onSubmit(AjaxRequestTarget target, Form<?> form) {
                        Alternative selected = alternativeListItem.getModelObject();
                        alternativeRepository.delete(selected);
                        getAlternatives().remove(selected);
                        target.addComponent(parent);
                    }
                });
                alternativeListItem.add(form);
                add(alternativeListItem);
            }
        });

        AjaxSubmitLink a = new AjaxSubmitLink("add") {
            @Override
            protected void onSubmit(AjaxRequestTarget target, Form<?> form) {
                Alternative alternative = new Alternative();
                MultipleChoiceQuestion mcq = (MultipleChoiceQuestion) getQuestion();
                alternative.setSequenceNumber(mcq.getAlternatives().size());
                alternative.setMultipleChoiceQuestion((MultipleChoiceQuestion) getQuestion());
                alternativeRepository.save(alternative);
                getAlternatives().add(alternative);
                target.addComponent(parent);
            }
        };
        a.setDefaultFormProcessing(false);
        form.add(a);
        parent.add(form);
    }
}

助けていただければ幸いです。

4

1 に答える 1

3

ListViewのJavadocから:

警告:フォーム内にListViewをネストすることはできますが、検証を正しく機能させるには、setReuseItemsプロパティをtrueに設定する必要があります。デフォルトでは、setReuseItemsはfalseです。これは、ListViewがすべての子コンポーネントを新しいインスタンスに置き換える効果があります。この背後にある考え方は、常に最新のデータをレンダリングすることです。人々は通常、読み取り専用リストを表示するためにListViewsを使用するため(少なくとも、これが私たちの考えです)、これは適切なデフォルトの動作です。

ただし、レンダリングが開始される前にコンポーネントが置き換えられるため、これらのコンポーネントの特定のメッセージの検索は、他のインスタンスに置き換えられるため失敗します。もう1つの問題は、「間違った」ユーザー入力がコンポーネントの(一時的な)インスタンスデータとして保持されることです。これらのコンポーネントは新しいコンポーネントに置き換えられるため、setReuseItemsがfalseの場合、ユーザーに間違ったデータが表示されることはありません。

それが本質的にここで起こることです。ListViewのReuseItemsをtrueに設定する必要があります。

于 2012-07-04T08:24:55.107 に答える