Java 如何将视图与模型更改/重新渲染同步

Java 如何将视图与模型更改/重新渲染同步,java,wicket,Java,Wicket,我有一个表单,其中包含一个文本字段输入,该输入绑定到模型对象中的字段。当用户在该文本字段中输入数据时,会根据计算结果影响表单中的多个其他字段/组件。我的业务逻辑封装在服务层中 理论上,我希望这样做的方式是,当用户更新字段时,会向服务器(在按键上)发出ajax调用,在服务器上应用来自服务的逻辑,并在模型对象上更新所有受影响的字段。在服务器上更新模型后,我希望将模型对象的当前状态同步到屏幕上 刷新整个屏幕是唯一的方法吗?是否有办法仅重新渲染绑定到模型中已更改字段的组件?另外,如果我刷新屏幕,正在编辑

我有一个表单,其中包含一个文本字段输入,该输入绑定到模型对象中的字段。当用户在该文本字段中输入数据时,会根据计算结果影响表单中的多个其他字段/组件。我的业务逻辑封装在服务层中

理论上,我希望这样做的方式是,当用户更新字段时,会向服务器(在按键上)发出ajax调用,在服务器上应用来自服务的逻辑,并在模型对象上更新所有受影响的字段。在服务器上更新模型后,我希望将模型对象的当前状态同步到屏幕上

刷新整个屏幕是唯一的方法吗?是否有办法仅重新渲染绑定到模型中已更改字段的组件?另外,如果我刷新屏幕,正在编辑的字段也会更新,有没有排除这种情况的方法

我对这种技术的任何最佳实践都感兴趣


谢谢

使用Ajax,您可以更新您想要的任何组件,只需确保它具有标记id(
Component.setOutputMarkupId(true)

您需要使用
ajaxFormComponentUpdateBehavior
ajaxFormChoiceComponentUpdateBehavior
,并且在其
onUpdate()
回调中,您必须更新相应
FormComponent
s的模型,然后您可以使用
FormComponent.this.getForm().visitChildren(FormComponent.class,IVisit)
访问当前表单的所有表单组件,并仅将已更新的组件添加到AjaxRequestTarget

更新 另一个好的解决方案(甚至更好!)是使用Wicket事件总线。在Ajax行为中,您可以广播一个事件:

component.send(getForm(), Broadcast.BREADTH, new UIChangedEvent(target, newValue));
其中,
UIChangedEvent
是您自己的类/POJO,它带来了更新组件和AjaxRequestTarget的新值


然后,其他FormComponents可以覆盖
#onEvent()
,并使用该值来计算其新值,并使用目标来更新自己或不更新自己,具体取决于先前的计算。

我从您的标记中假设您正在使用wicket。Wicket为此目的使用行为。在下面的示例中,如果文本字段的输入发生更改,您将更新这两个下拉选项。您只需要将这些控件添加到AjaxRequestTarget。这两个下拉选项的模型将在前端重新加载和重新招标。还要确保在要更新的控件上调用setOutputMarkupId(true)

    TextField<String> textField = new TextField<String>("input");
    Component dropDownA = new DropDownChoice<>("dropA").setOutputMarkupId(true);
    Component dropDownB = new DropDownChoice<>("dropB").setOutputMarkupId(true);

    textField.add(new AjaxFormComponentUpdatingBehavior("change") {
        private static final long serialVersionUID = 1478280524536023725L;

        @Override
        protected void onUpdate(AjaxRequestTarget target) {
            target.add(dropDownA);
            target.add(dropDownB);
        }
    });
TextField TextField=新的TextField(“输入”);
组件dropDownA=新的DropDownChoice(“dropA”)。setOutputMarkupId(真);
Component dropDownB=新的DropDownChoice(“dropB”)。setOutputMarkupId(真);
添加(新的AjaxFormComponentUpdateingBehavior(“更改”){
私有静态最终长serialVersionUID=1478280524536023725L;
@凌驾
受保护的void onUpdate(AjaxRequestTarget目标){
target.add(dropDownA);
target.add(dropDownB);
}
});

最佳实践是使用从AJAX响应回调调用的Javascript来更新字段。应指定事件类型,而不使用
on
前缀。所以在这种情况下,它只是
change
而不是
onchange
。请参阅Wicket 7中的
AjaxEventBehavior
中的以下警告:“由于版本6.0.0 Wicket使用JavaScript事件注册,因此事件名称“%s”中不需要前导的“on”。请仅使用“%s”。Wicket 8.x不会操纵提供的事件名称,因此前导的“on”可能会破坏您的应用程序。感谢您提供的信息。我没有意识到这一点,并更改了about语句。感谢您的回复Martin,我真正想要的是使用视图重新渲染器,但仅限于那些具有与当前屏幕上不同值的字段,而无需通过添加以下行为显式创建依赖项:“更新更改字段A、B、C、F、X“。如果您建议只添加已更新的字段,是否有办法通过wicket确定哪些字段已更新?或者你必须参考原始模型并逐字段进行比较吗?嗨,马丁,我个人不喜欢带有新价值观的事件。我认为它们应该由组件自己设置在适当的模型上。事件应由处理模型(或衍生模型)的组件处理,然后这些组件重用模型中的数据。这可以防止“谁负责更新模型”的bug