Java ApacheWicket:验证错误后如何更新模型

Java ApacheWicket:验证错误后如何更新模型,java,apache,validation,wicket,Java,Apache,Validation,Wicket,我有dateTimeField和ListView的表单。 ListView看起来是这样的: final ListView<String> countryView = new ListView<String>("country", model.<List<String>>bind("country")) { @Override protected void populateItem(final List

我有dateTimeField和ListView的表单。 ListView看起来是这样的:

final ListView<String> countryView = new ListView<String>("country", model.<List<String>>bind("country")) {
            @Override
            protected void populateItem(final ListItem<String> item) {
                    final String country = item.getModelObject();
                    item.add(new ValidationDisplayableLabel("country", country, new String[] { modelPath }));
                    item.add(new AjaxLink("deleteLink") {
                        @Override
                        public void onClick(AjaxRequestTarget target) {
                            model.getObject().getCountry().remove(country);
                            if (issPeriod) {
                                addButton.setVisible(true);
                                countryTextField.setVisible(true);
                                findButton.setVisible(true);
                            }
                            if (target != null)
                                target.addComponent(rowPanel);
                        }
                    });
            }
        };
        countryTextField = new ValidationDisplayableTextField("countryCodeInput", model.bind("oneCountry"), "job.country.value");

        **countryView.setReuseItems(true);**
        rowPanel.add(countryView);
        rowPanel.add(countryTextField);
        addButton.setOutputMarkupPlaceholderTag(true);
        rowPanel.add(addButton);
AjaxSubmitLink addButton = new AjaxSubmitLink(LinkNames.addCountry.toString()) {
        @Override
        public void onSubmit(AjaxRequestTarget target, Form form) {
            if (model.getObject().getOneCountry() != null)
                addCountry();
                if (target != null)
                    target.addComponent(rowPanel);
                target.addComponent(form.getPage().get("feedbackPanel"));
        }
        @Override
        protected void onError(AjaxRequestTarget target, Form<?> form)
        {
            onSubmit(target, form);
        }
    };
final ListView countryView=新列表视图(“国家”,model.bind(“国家”)){
@凌驾
受保护的无效填充项(最终列表项){
最后一个字符串country=item.getModelObject();
add(新的ValidationDisplayableLabel(“country”,country,新字符串[]{modelPath}));
添加(新的AjaxLink(“删除链接”){
@凌驾
公共void onClick(AjaxRequestTarget目标){
model.getObject().getCountry().remove(国家);
如有(第二期){
addButton.setVisible(true);
countryTextField.setVisible(true);
设置可见(true);
}
如果(目标!=null)
target.addComponent(行面板);
}
});
}
};
countryTextField=new ValidationDisplayableTextField(“countryCodeInput”、model.bind(“oneCountry”)、“job.country.value”);
**countryView.setReuseItems(true)**
rowPanel.add(countryView);
rowPanel.add(countryTextField);
addButton.setOutputMarkupPlaceholderTag(真);
rowPanel.add(添加按钮);
addButton看起来像这样:

final ListView<String> countryView = new ListView<String>("country", model.<List<String>>bind("country")) {
            @Override
            protected void populateItem(final ListItem<String> item) {
                    final String country = item.getModelObject();
                    item.add(new ValidationDisplayableLabel("country", country, new String[] { modelPath }));
                    item.add(new AjaxLink("deleteLink") {
                        @Override
                        public void onClick(AjaxRequestTarget target) {
                            model.getObject().getCountry().remove(country);
                            if (issPeriod) {
                                addButton.setVisible(true);
                                countryTextField.setVisible(true);
                                findButton.setVisible(true);
                            }
                            if (target != null)
                                target.addComponent(rowPanel);
                        }
                    });
            }
        };
        countryTextField = new ValidationDisplayableTextField("countryCodeInput", model.bind("oneCountry"), "job.country.value");

        **countryView.setReuseItems(true);**
        rowPanel.add(countryView);
        rowPanel.add(countryTextField);
        addButton.setOutputMarkupPlaceholderTag(true);
        rowPanel.add(addButton);
AjaxSubmitLink addButton = new AjaxSubmitLink(LinkNames.addCountry.toString()) {
        @Override
        public void onSubmit(AjaxRequestTarget target, Form form) {
            if (model.getObject().getOneCountry() != null)
                addCountry();
                if (target != null)
                    target.addComponent(rowPanel);
                target.addComponent(form.getPage().get("feedbackPanel"));
        }
        @Override
        protected void onError(AjaxRequestTarget target, Form<?> form)
        {
            onSubmit(target, form);
        }
    };
AjaxSubmitLink addButton=新的AjaxSubmitLink(LinkNames.addCountry.toString()){
@凌驾
提交时公共无效(AjaxRequestTarget目标,表单){
如果(model.getObject().getOneCountry()!=null)
addCountry();
如果(目标!=null)
target.addComponent(行面板);
target.addComponent(form.getPage().get(“feedbackPanel”);
}
@凌驾
受保护的void onError(AjaxRequestTarget目标,表单)
{
onSubmit(目标、形式);
}
};
问题是,当我的DateTime字段失败时(例如,将小时数设置为100),在countryTextField中输入国家代码,然后按add按钮,它会在反馈面板中显示验证消息,小时范围不正确,但不添加国家。这是因为我的模型没有更新。也许有办法手动更新它?所以会显示验证消息,但国家/地区列表视图仍然可以更新

整个表单的提交在另一个按钮上,所以从逻辑上讲,添加国家是正常的,即使dateTimeField中存在验证错误

谢谢

另外,我已经读了很多关于类似问题的帖子,但大多数都是用.setReuseItems(true)解决的,但在我的案例中它不起作用


p.p.S ApacheWicket 1.4.17

在我的项目中,我遇到了一个类似的问题,我发现的解决方法是使用一个特殊的访问者。即使提交的输入无效,它也会更新模型

public class VisitorUpdateModelWithoutValidation implements FormComponent.IVisitor {

public Object formComponent(IFormVisitorParticipant formComponent) {
        if (formComponent instanceof FormComponent) {
            final FormComponent<?> formComponent1 = (FormComponent<?>) formComponent;
            boolean required = formComponent1.isRequired();
            if (required) {
                formComponent1.setRequired(false);
            }
            formComponent1.modelChanging();
            formComponent1.validate();
            formComponent1.updateModel();
            formComponent1.modelChanged();
            if (required) {
                formComponent1.setRequired(true);
            }
        }

        return Component.IVisitor.CONTINUE_TRAVERSAL;
    }
}
公共类VisitorUpdateModelWithout验证实现FormComponent.IVisitor{
公共对象formComponent(IFormVisitorParticipant formComponent){
if(formComponent的formComponent实例){
最终FormComponent FormComponent 1=(FormComponent)FormComponent;
布尔值required=formComponent1.isRequired();
如果(需要){
formComponent1.setRequired(false);
}
formComponent1.modelChanging();
formComponent1.validate();
formComponent1.updateModel();
formComponent1.modelChanged();
如果(需要){
formComponent1.setRequired(true);
}
}
返回Component.IVisitor.CONTINUE\u遍历;
}
}

只需在行为的
onSubmit
方法中使用它:
getForm().visitFormComponents(新的VisitorUpdateModelWithoutValidation())

作为此答案的更新,在Wicket 6中,您可以通过覆盖以下形式的onError()来完成此操作:

@Override
    protected void onError() {
    super.onError();
    this.updateFormComponentModels();
}

您可以在目标更新之前对正在更新的字段发出
field.clearInput()

对我来说,这感觉非常糟糕,不是您的代码,而是wicket不会更新模型,除非表单经过验证。我不明白您的观点。验证器的目的是确保模型对象不包含无效数据。更新它们没有多大意义。模型更新限制仅在表单提交(通常)时才重要。此wicket行为不仅在提交时限制模型更新,而且在任何其他事件中也会限制模型更新。例如,我的复选框“其他组件的模型更新”事件在验证错误后将永远不会在屏幕上显示当前状态。对我来说,这是一些“邪恶”的小门行为。这是非常有帮助的。谢谢!