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.