An often asked question is how to show a confirmation dialog before ‘comitting’ a link. The easiest way to do that is something like this:
Link remove = new Link("removeFieldLink") {
@Override
public void onClick() {
FieldDefinition definition = (FieldDefinition) item.getModelObject();
programService.deleteFieldDefinition(definition);
}
};
remove.add(new SimpleAttributeModifier(
"onclick", "return confirm(’remove definition?’);"));
But say you don’t want to do this by using JavaScript? Make it an abstract reusable component, like Ed Eustace did for Teachscape and use it like this:
Link remove = new Link("removeFieldLink") {
@Override
public void onClick() {
ManageProfileFieldsPanel.this.replaceWith(
new ConfirmDeletePanel(ManageProfileFieldsPanel.this.getId(),
"really delete?") {
@Override
protected void onCancel() {
this.replaceWith(ManageProfileFieldsPanel.this);
}
@Override
protected void onConfirm() {
FieldDefinition definition =
(FieldDefinition) item.getModelObject();
programService.deleteFieldDefinition(definition);
this.replaceWith(ManageProfileFieldsPanel.this);
}
});
}
};
Note the replaceWith trick. The ConfirmDeletePanel doesn’t have to know about what context it runs in, and we’re creating it with same id as the component we’re going to replace (the current this, ManageProfileFieldsPanel.this).
The ConfirmDeletePanel can be written like this:
public abstract class ConfirmDeletePanel extends Panel {
public ConfirmDeletePanel(String id, String message) {
super(id);
add(new Label("message", message));
add(new Link("confirm") {
@Override
public void onClick() {
onConfirm();
}
});
add(new Link("cancel") {
@Override
public void onClick() {
onCancel();
}
});
}
protected abstract void onCancel();
protected abstract void onConfirm();
}
and I’m sure you can think of some suitable HTML that goes with it :)
UPDATE: I just looked at this again, and realized you could make it work more magical if you prefer to save a few strokes.
public abstract class ConfirmDeletePanel extends Panel {
private final WebMarkupContainer previous;
private ConfirmDeletePanel(WebMarkupContainer parent, String message) {
super(parent.getId());
this.previous = parent;
parent.replaceWith(this);
add(new Label("message", message));
add(new Link("confirm") {
@Override
public void onClick() {
onConfirm();
ConfirmDeletePanel.this.replaceWith(previous);
}
});
add(new Link("cancel") {
@Override
public void onClick() {
onCancel();
}
});
}
protected void onCancel() {
ConfirmDeletePanel.this.replaceWith(previous);
};
protected abstract void onConfirm();
}
which can then be used like this:
Link remove = new Link("removeFieldLink") {
@Override
public void onClick() {
new ConfirmDeletePanel(ManageProfileFieldsPanel.this, "really delete?") {
@Override
protected void onConfirm() {
FieldDefinition definition =
(FieldDefinition) item.getModelObject();
programService.deleteFieldDefinition(definition);
}
});
}
};
I think I prefer the more explicit version myself, but if you like your code more compact, this might work for you :-)

