We have a trouble in our wicket 6 project. We have a form which is loading via AJAX.
When our form fails validation we can't load other object into the model correcly (fields that have failed are empty).
I'm trying to create new object (my modelobject value = new MyObject()) and validation fails :
Then if I choose already created object from the tree on the left side I can see empty fields :
But really this object has all the fields setted :
Form markup:
<wicket:panel>
<div wicket:id="feedback"></div>
<form wicket:id="form" role="form" class="form-horizontal">
<div class="form-group">
<label wicket:for="shortName" class="control-label col-sm-4"><wicket:message key="shortName"></wicket:message></label>
<div class="col-sm-8">
<input type="text" class="form-control" wicket:id="shortName" />
</div>
</div>
<div class="form-group">
<label wicket:for="fullName" class="control-label col-sm-4"><wicket:message key="fullName"></wicket:message></label>
<div class="col-sm-8">
<input type="text" class="form-control" wicket:id="fullName" />
</div>
</div>
<div class="form-group">
<label wicket:for="parentServiceGroup" class="control-label col-sm-4"><wicket:message key="parentServiceGroup"></wicket:message></label>
<div class="col-sm-8">
<select type="text" class="form-control width-abs" wicket:id="parentServiceGroup"></select>
</div>
</div>
<div class="form-group">
<label wicket:for="status" class="control-label col-sm-4"><wicket:message key="status"></wicket:message></label>
<div class="col-sm-8">
<select class="form-control width-abs" wicket:id="status"></select>
</div>
</div>
<div>
<a wicket:id="save" class="btn btn-primary"></a>
<a wicket:id="cancel" class="btn btn-default"></a>
</div>
</form>
</wicket:panel>
Form code :
@Override
protected void onInitialize() {
super.onInitialize();
add(new MiraFeedbackPanel("feedback"));
final Form form = new Form("form", CompoundPropertyModel.of(getDefaultModel())) {
@Override
protected void onError() {
super.onError();
this.updateFormComponentModels();
}
};
add(form);
form.add(new TextField("shortName").setRequired(true));
form.add(new TextField("fullName"));
form.add(new DropDownChoice("status", Arrays.asList(CommonStatus.values()),
new ChoiceRenderer<CommonStatus>("name")).setRequired(true));
form.add(new ServiceGroupDropDownChoice("parentServiceGroup", getServiceGroupModelObject()));
form.add(new AjaxSubmitLabeledLink("save", "Save", form) {
@Override
protected void onError(AjaxRequestTarget target, Form<?> form) {
super.onError();
error(getString("savingError"));
target.add(ServiceGroupEditPanel.this.get("feedback"));
}
@Override
protected void onSubmit(AjaxRequestTarget target, Form<?> form) {
getServiceGroupModelObject().setDateCreated(new Date());
getServiceGroupModelObject().setWorkerCreated(UserSession.get().getWorker());
getServiceGroupModelObject().setDateModification(new Date());
getServiceGroupModelObject().setWorkerModification(UserSession.get().getWorker());
DAOService.ejbCommonBean().saveEntity(getServiceGroupModelObject());
info(getString("serviceGroupSaved"));
target.add(ServiceGroupEditPanel.this.get("feedback"));
target.add(ServiceGroupEditPanel.this.getParent().getParent()
.get("serviceGroupsTree"));
}
});
form.add(new AjaxLabeledLink("cancel", "Cancel") {
@Override
public void onClick(AjaxRequestTarget target) {
getServiceGroupModel().setObject(null);
target.add(ServiceGroupEditPanel.this.getParent().getParent()
.get("serviceGroupsTree"));
target.add(ServiceGroupEditPanel.this.getParent().getParent()
.get("serviceNotSet"));
target.add(ServiceGroupEditPanel.this.getParent().getParent()
.get("selectedServiceGroup"));
target.add(ServiceGroupEditPanel.this.getParent());
}
});
}
We tried the workaround from this issue : Apache wicket: how to update model after validation error but it didn't helped.
UPD: Code of tree from where I'm trying to update model :
add(new DefaultNestedTree<ServiceGroup>("serviceGroupsTree", new ServiceGroupsTreeProvider()) {
@Override
protected Component newContentComponent(String id, IModel<ServiceGroup> node) {
return new Folder<ServiceGroup>(id, this, node) {
@Override
protected Component newLabelComponent(String id, IModel<ServiceGroup> model) {
return new Label(id, PropertyModel.of(model, "shortName"));
}
@Override
protected MarkupContainer newLinkComponent(String id, final IModel<ServiceGroup> model) {
return new AjaxLink(id, model) {
@Override
public void onClick(AjaxRequestTarget target) {
serviceGroupModel.setObject(DAOService.ejbCommonBean()
.getEntityFullFetch(
ServiceGroup.class,
model.getObject().getUidservicegroup()
));
target.add(ServiceGroupListPage.this.get("selectedServiceGroup"));
target.add(ServiceGroupListPage.this.get("serviceNotSet"));
target.add(ServiceGroupListPage.this.get("tabs"));
((ServiceGroupEditPanel)editPanelTab.getPanel("editTab")).onModelObjectChanged(target);
}
};
}
};
}
}
Our form added to the AjaxTabbedPanel :
final ServiceGroupEditPanelTab editPanelTab = new ServiceGroupEditPanelTab("editTab", serviceGroupModel);
List<ITab> tabsList = new ArrayList<>();
tabsList.add(editPanelTab);
tabsList.add(new ServiceGroupServicesPanelTab("servicesTab", serviceGroupModel));
final AjaxTabbedPanel tabs = new AjaxBootstrapTabbedPanel("tabs", tabsList);
tabs.setSelectedTab(0);
add(tabs);
UPD2:
I've added the sample project to Github to show my problem. In README.md
there are steps to reproduce the error.
If you're just swapping the object in your model, all your form components will still hold the previous raw input.
Call Form#clearInput() after you've changed your model object, i.e. after you've chosen a different entity from your tree.