The solution is to add an AjaxCallDecorator to your button, as follows:
public class MyAjaxDeleteButton extends IndicatingAjaxButton
private static final long serialVersionUID = -8294444630452310166L;
private final IModel confirm;
public MyAjaxDeleteButton(String id, IModel confirm, IModel label)
this.confirm = confirm;
protected IAjaxCallDecorator getAjaxCallDecorator()
return new AjaxPreprocessingCallDecorator(super.getAjaxCallDecorator())
private static final long serialVersionUID = 7495281332320552876L;
public CharSequence preDecorateScript(CharSequence script)
return "if(!confirm('" + confirm.getObject()
+ "')) return false;" + script;
Note that the confirmation message is passed in as a model. This is because, if you use a localized string, and you look it up using Localizer.getString() in the constructor of your page, Wicket will complain because it can't properly navigate the component hierarchy to resolve localized properties until after all components have been constructed. If you use a model, you won't have this problem.
Example of how to use it:
private class DeleteButton extends MyAjaxDeleteButton
private static final long serialVersionUID = 4966354164332401574L;
// MyDataPanel.properties contains:
// confirmdelete=Are you sure you want to delete?
super("delete", new StringResourceModel("confirmdelete", MyDataPanel.this,
null), new StringResourceModel("delete", MyDataPanel.this,
protected void onSubmit(AjaxRequestTarget target, Form form)
// Update the feedback panel
final MyBasePage page = (MyBasePage) this.getWebPage();
// Do the actual deletion here...
// Update the data panel
Note that I'm adding my feedback panel to the Ajax target. This way, any errors will be shown as well. This does depend on calling
feedback.setOutputMarkupId(true) in your base page.