Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Wicket page is refreshed if use ajax after form is submitted with target=_blank

Tags:

ajax

wicket

I have a preview button. When user press preview, form is submitted on new tab to show a pdf file have data in form. I use a custom SubmitLink to do that SubmitResourceLink

public abstract class SubmitResourceLink extends SubmitLink implements IResourceListener {
private final IResource resource;

@Override
public final void onResourceRequested() {
    Attributes a = new Attributes(RequestCycle.get().getRequest(), RequestCycle.get().getResponse(), null);
    resource.respond(a);
}

Implement on form

new SubmitResourceLink("previewBtn", form, new JasperReportsResource() {
        private static final long serialVersionUID = -2596569027102924489L;

        @Override
        public byte[] getData(Attributes attributes) {
            return control.getExportPreviewByteStream(estimateModel.getObject());
        }
    }) {
        private static final long serialVersionUID = 1L;

        @Override
        protected String getTriggerJavaScript() {
            String js = super.getTriggerJavaScript();
            js = "document.getElementById('" + form.getMarkupId() + "').target='_blank';" + js;
            return js;
        }

        @Override
        public void onSubmit() {
            form.add(AttributeModifier.append("target", Model.of("_blank")));
            processInputs(form);
            onResourceRequested();
        }
    }.setDefaultFormProcessing(false);

When I press preview, a new tab is opend. But when I input in any ajax component (ex:AutoCompleteTextField), ajax reponse data xml: <ajax-response><redirect>....</redirect></ajax-response> and refresh page. Now, I want after press preview, I still use current form normaly. Thank.

like image 655
luanvu Avatar asked Nov 10 '22 12:11

luanvu


1 Answers

This is caused by the "stale page protection" in Wicket. The first click opens the same page instance in a new tab/window. This increments the page's renderCount counter, i.e. it says "this page has been rendered N times".
The links in Wicket look like ?2-1.ILinkListener-component~path. Here '2' is the page id and '1' is the page render count. So the links in tab1 have renderCount 'N', and the links in tab2 - 'N+1'.
Clicking on a link in tab1 will fail with StalePageException that tells Wicket "the user is trying to use an obsolete version of the page. Please render the latest version of the page so the user can try again".

This protection is needed because the user may do many actions in tab3, e.g. replace a panel that replaces/hides the link the user wants to click in tab1. If there is no such protection Wicket will either fail with ComponentNotFoundException while trying to click the Link or even worse can do the wrong action if the Link/Button is in a repeater and the repeater has changed its items in tab2.

To overcome your problem you should open a new page instance in tab2, i.e. it submits the form but in onSubmit() does something like setResponsePage(getPage().getClass()). This way it won't re-render the current page instance N+1 time.

like image 198
martin-g Avatar answered Nov 15 '22 11:11

martin-g