For those who are not very clear about wicket basics I would suggest to go through this nice article Introducing Apache Wicket by Nick Heudecker.
Wicket developers usually find this requirement to add different Panels and Validators to Form dynamically, means the actual implementation of the Panel and Validator is not know while creating the wicket page. I will walk you through an example that shows how we can do this.
Lets say we have a wicket page containing two panels, one top panel which displays some list and bottom panel which shows the details of the selected item from the list. The details of the each item may be different like one item showing TextField component and another showing DropDownChoice component and both have some Label as common component.
Top List Panel – TestListPanel:
—————–
public class TestListPanel extends Panel {
public TestListPanel(String id, TestDetailsPanel testDetailsPanel) {
super(id);
this.testDetailsPanel = testDetailsPanel;
addComponents();
}
private void addComponents() {
Form form = new Form(“testListForm”) {
@Override
protected void onSubmit() {
selectedTestListId = selectedTestListIdField.getModelObjectAsString();
if (StringUtils.isNotBlank(selectedTestListId)) {
testDetailsPanel.showDetails(Long.parseLong(selectedTestListId));
}
}
};
…..
…..
}
———–
The list panel contains the details panel and the testListForm submits the selectedTestListId which calls the showDetails method on details panel which will show the details of the panel.
Test model – TestModel:
—————
public class TestModel implements Serializable, IModel {
private String name;
private String description;
private List<String> choices;
…
….
}
———–
This is the view model for the page which keeps data to be shown on the page.
Details Panel – TestDetailsPanel :
———————
public class TestDetailsPanel extends Panel {
private TestModel testModel;
private DetailsPanel detailsPanel = null;
private TestValidator testValidator = null;
private Form detailsForm;
…..
….
public void showDetails(long id) {
testModel = testService.getModel(id));
detailsForm.setModel(new CompoundPropertyModel(testModel));
if (“textField”.equals(testModel.getType())) {
detailsPanel = new TextFieldDetailsPanel(“detailsPanel”, testModel);
} else if (“dropDownChoice”.equals(testModel.getType())) {
detailsPanel = new DropDownChoiceDetailsPanel(“detailsPanel”, testModel);
}
if (testValidator != null) {
detailsForm.remove(testValidator);
}
testValidator = detailsPanel.getValidator(testValidator);
detailsForm.add(testValidator);
detailsForm.addOrReplace(detailsPanel);
}
…
..
}
——————————
The details panel loads the model testModel to get the Model data from testService. Depending on the type of the testType.getType() (some criteria) the implementation of details panel assigned. Using addOrReplace method the form is added or replaced to the Form.
Lets have a look at the implementation of these different panels.
Common details panel – DetailsPanel:
——————
public abstract class DetailsPanel extends Panel {
private Label nameLabel;
public DetailsPanel(String id, TestModel testModel) {
super(id);
nameLabel = new Label(“name”,testModel.getName());
addOrReplace(nameLabel);
}
abstract testValidator getValidator(TestValidator testValidator);
…
…
}
——————–
The common details panel contains the common information between all panels.
TextField details panel – TextFieldDetailsPanel:
———–
public class TextFieldDetailsPanel extends DetailsPanel {
public TextFieldDetailsPanel(String id, TestModel testModel) {
super(id, testModel);
add(new TextField(“description”, new PropertyModel(testModel, “description”)));
}
public TestValidator getValidator(TestValidator testValidator) {
testValidator = new TestValidator(<text field related validation>);
return testValidator;
}
…
…
}
——————-
TextFieldDetailsPanel extends DetailsPanel and so getting nameLabel information and new component TextField is added for this implementation of the DetailsPanel. The getValidator will give this panel data dependent implementation of the validator and will do the validation of the description textField.
Drop down choice details panel – DropDownChoiceDetailsPanel:
——–
public class DropDownChoiceDetailsPanel extends DetailsPanel {
public DropDownChoiceDetailsPanel(String id, TestModel testModel) {
super(id, testModel);
add(new DropDownChoice(“dropDownChoices”, new PropertyModel(testModel, “choices”)));
}
public TestValidator getValidator(TestValidator testValidator) {
testValidator = new TestValidator(<drop down choice related validation>);
return testValidator;
}
…
…
}
—————
The same way DropDownChoiceDetailsPanel is implemented. But here instead of TextField, DropDownChoice component is added. And the different drop down choice based validation is done for this panel.
Even the validator could have been added the same way but here it is kept as single instance of testValidator which is kept at form level.
This is very simple example in terms of complexity of the actual presentation page. Just think of very complex page and design your wicket components in a very loosely coupled components.