tags:

views:

121

answers:

1

I've got a simple Wicket form that lets users select some data and then download a ZIP file (generated on the fly) containing what they asked for. Currently the form button's onSubmit() method looks something like this:

public void onSubmit() {
    IResourceStream stream = /* assemble the data they asked for ... */ ;
    ResourceStreamRequestTarget target = new ResourceStreamRequestTarget(stream);
    target.setFileName("download.zip");
    RequestCycle.get().setRequestTarget(target);
}

This works, but of course the request stops there and it's impossible to display any other feedback to the user.

What I'd like to have is something like the typical "Your requested download [NAME] should begin automatically. If not, click this link." Ideally, still displaying the same page, so the user can immediately select some different data and download that as well.

I imagine it's possible to do this using Wicket's Ajax classes, but I've managed to avoid having to use them so far, and it's not immediately obvious to me how. What's my quickest way out, here?


Updated per answer from Zeratul, below: what I ended up with was something like this:

class MyDownloader extends AbstractAjaxBehavior {

    private final MyForm form;

    MyDownloader(MyForm form) {
        this.form = form;
    }

    void startDownload(AjaxRequestTarget target) {
        target.addComponent(myForm);
        target.appendJavascript("window.location.href='" + getCallbackUrl() + "'");
    }

    @Override
    public void onRequest() {
        try {
            ResourceStreamRequestTarget streamTarget = form.getStreamTarget();
            form.info(/* some status message */);
            getComponent().getRequestCycle().setRequestTarget(streamTarget);
        catch (SomeException e) {
            form.error(e.getMessage());
        }
    }
}

class MyForm extends Form {

    private final MyDownloader myDownloader;
    private final Object myModel;

    MyForm(Object aModel) {
        super("myForm");
        myModel = aModel;
        myDownloader = new MyDownloader(this);

        add(myDownloader);

        add(/* form components */);
        add(new AjaxButton("download", new Model<String>("Download"), this) {
            @Override
            protected void onSubmit(AjaxRequestTarget target, Form<?> form) {
                myDownloader.startDownload(target);
            }
        });

        add(new FeedbackPanel("feedback"));
    }

    ResourceStreamRequestTarget getStreamTarget() throws SomeException {
        return /* target based on form input */;
    }
}

This feels a bit rickety, but it seems to work.

A: 

There is an article on Apache cwiki about this, it may suit you:

ajax download

Zeratul
That looks as though it should solve the problem, and the download part does work, but unfortunately it doesn't tell me anything about how to actually update the page -- the example suggests adding components to the AjaxRequestTarget, but it's not clear what the target actually is or where those components end up.
David Moles
Okay, figured it out -- just had to add the enclosing form to the target. Weird API, but it works. Thanks.
David Moles