Search code examples
tabswicket

My Wicket TabbedPanel doesn't keep the form field values


I'm new using Apache Wicket. I'm creating a panel to add articles on a web site. My panel to edit an article is formed with a TabbedPanel: the first tab is to edit and the second tab is to preview the article.

If after I entered some text in the editor (textarea), I switch to the preview and go back to the editor, le textarea is empty.

Here a part of the code for the panel with the TabbedPanel:

public AddArticlePanel(String id, ArticleEdit articleEdit) {
        super(id);

        final List<AbstractTab> tabList = new ArrayList<>();
        tabList.add(new AbstractTab(new Model<String>("Editor")) {
            @Override
            public WebMarkupContainer getPanel(String panelId) {
                return new ArticleEditorPanel(panelId, articleEdit);
            }
        });
        tabList.add(new AbstractTab(new Model<String>("Preview")) {
            @Override
            public WebMarkupContainer getPanel(String panelId) {
                return new ArticlePreviewPanel(panelId, articleEdit);
            }
        });
        tabs = new TabbedPanel<AbstractTab>("tabs", tabList);

        final SubmitLink submitButton = new SubmitLink("submit") {
            @Override
            public void onSubmit() {
                // TODO
            }
        };

        addArticleForm = new Form<ArticleEdit>("add-article-form", new Model<ArticleEdit>(articleEdit));
        addArticleForm.add(tabs);
        addArticleForm.add(submitButton);
        add(addArticleForm);
    }

Here the HTML for the editor panel:

<wicket:panel>
        <div wicket:id="feedback"></div>

        <div class="fields">
            <label for="title">Title</label>
            <input type="text" name="title" wicket:id="title">
        </div>
        <div class="fields">
            <label for="text">Text</label>
            <textarea class="notab" name="text" wicket:id="text"></textarea>
        </div>
        <div class="fields">
            <label for="keywords">Keywords</label>
            <input type="text" name="keywords" wicket:id="keywords">
        </div>
</wicket:panel>

The code for this editor panel:

public ArticleEditorPanel(String id, ArticleEdit articleEdit) {
        super(id);

        final FeedbackPanel feedbackPanel = new FeedbackPanel("feedback");

        title = new TextField<String>("title", new PropertyModel<String>(articleEdit, "title"));
        title.setRequired(true);

        text = new TextArea<String>("text", new PropertyModel<String>(articleEdit, "text"));
        text.setRequired(true);

        keywords = new TextField<String>("keywords", new PropertyModel<String>(articleEdit, "keywords"));
        keywords.setRequired(true);

        add(title);
        add(text);
        add(keywords);
        add(feedbackPanel);
    }

Finally, the source code of the ArticleEdit class:

public class ArticleEdit implements Serializable {

    private String title;

    private String text;

    private String keywords;

    private String preview;

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getText() {
        return text;
    }

    public void setText(String text) {
        this.text = text;
    }

    public String getKeywords() {
        return keywords;
    }

    public void setKeywords(String keywords) {
        this.keywords = keywords;
    }

    public String getPreview() {
        return preview;
    }

    public void setPreview(String preview) {
        this.preview = preview;
    }
}

Why it doesn't work out of the box ? Where is my mistake ?

Thank you for your help.


Solution

  • You do not save the state from your EDIT tab before navigating to the PREVIEW tab.

    By clicking the "Preview" link the browser will make a new request to the server and Wicket will re-render the whole page, so any data entered in the form fields will be lost.

    You can easily save the data by adding AjaxFormComponentUpdatingBehavior to the form fields. For example for the title field:

    title = new TextField<String>("title", new PropertyModel<String>(articleEdit, "title"));
    title.setRequired(true);
    title.add(new AjaxFormComponentUpdatingBehavior("change") {
        @Override public void onUpdate(AjaxRequestTarget target) {}
        @Override public void onError(AjaxRequestTarget target) {
             target.add(feedbackPanel);
        }
    });