Wicket Form 在验证失败后加载空值

Wicket Form loads empty values after validation fails

我们的 wicket 6 项目遇到了麻烦。我们有一个通过 AJAX 加载的表单。

当我们的表单验证失败时,我们无法将其他对象正确加载到模型中(验证失败的字段为空)。

我正在尝试创建新对象(我的模型对象值 = new MyObject())但验证失败:

然后,如果我从左侧的树中选择已经创建的对象,我会看到空字段:

但实际上这个对象设置了所有字段:

表单标记:

<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>

表单代码:

@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());
        }
    });
}

我们尝试了这个问题的解决方法:Apache wicket: how to update model after validation error 但没有用。

UPD:我尝试更新模型的树代码:

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);
                        }
                    };
                }
            };
        }
    }

我们的表单添加到 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: 我添加了 sample project to Github 来显示我的问题。 README.md 中有重现错误的步骤。

如果您只是交换模型中的对象,您的所有表单组件仍将保留之前的原始输入。

在更改模型对象后调用 Form#clearInput(),即在您从树中选择不同的实体后。