【问题标题】:MVVM binding, get previous form values before savingMVVM 绑定,保存前获取之前的表单值
【发布时间】:2016-12-26 16:14:32
【问题描述】:

问题

我有一个Person 对象,可以在弹出窗口中进行编辑。

我需要知道,当表单被保存时,是否有一些值发生了变化

我正在使用 全局变量 来存储对象的初始状态,但似乎该变量也已更新而我没有不明白为什么。


代码

看一下代码,它更明确(我已经删除了不相关的代码,这样更容易阅读):

模型Person.java):

@Entity
@Table(name = "person")
public class Person {

    @Column
    private String lastName;

    @Column
    private String firstName;

}

查看模型PersonVm.java):

@VariableResolver(org.zkoss.zkplus.spring.DelegatingVariableResolver.class)
public class PersonVm {

    private Person person;
    private static Person initialPerson;
    private PersonGroupingVm personGroupingModel;

    @Init
    public void init(@ExecutionArgParam("person") Person pers, @ContextParam(ContextType.VIEW) Component view) {
        Selectors.wireComponents(view, this, false);
        if (pers != null) 
            person = pers;
        setPersonGroupingModel(new PersonGroupingVm(personMgr.getPersons(), new PersonComparator(), false));
    }

    @Command
    @NotifyChange("person")
    public void openEditPersonDialog(@BindingParam("person") Person pers) {
        initialPerson = pers;
        Map<String, Object> args = new HashMap<String, Object>();
        args.put("person", pers);
        Executions.createComponents(".../editPerson.zul", null, args);
    }

    @Command
    @NotifyChange("person")
    public void savePerson() {
        Clients.alert(person.equals(initialPerson) + "");
        Clients.alert(person.getFirstName());
        Clients.alert(initialPerson.getFirstName());
        // person and initialPerson both contain new values !
    }

}

查看persons.zul):

<vlayout apply="org.zkoss.bind.BindComposer" viewModel="@id('vm') @init('ch.myorg.vm.PersonVm')">
    <grid model="@load(vmp.personGroupingModel)">
        ...
        <template name="model" var="pers">
            <row>
                <label value="@load(pers.firstName)"/>
                <label value="@load(pers.lastName)"/>
                <button onClick="@command('openEditPersonDialog', person=pers)"/>
            </row>
        </template>
    </grid>
</vlayout>

查看editPersonDialog.zul):

<window apply="org.zkoss.bind.BindComposer" viewModel="@id('vm') @init('ch.myorg.vm.PersonVm')">
    <div form="@id('p') @load(vm.person) @save(vm.person, before='savePerson')">
        <textbox value="@bind(p.firstName)"/>
        <textbox value="@bind(p.lastName)"/>
        <button label="${labels.action.validate}" onClick="@command('savePerson')"/>
    </div>
</window>

为什么我的 2 个对象(personinitialPerson)包含新值?仅绑定了person 对象。

【问题讨论】:

    标签: java mvvm data-binding viewmodel zk


    【解决方案1】:

    快速回答:Java 通过引用威胁对象,这意味着 2 个变量指向相同的内存位置。

    现在有一些解决方案。

    第一个解决方案是从数据库中获取一个新对象作为原始对象。
    但是,如果您这样做 => 这应该是更多用于服务器而不是 GUI 部分的代码。

    第二种解决方案是使用form.
    仅当某些数据已更改时,您才会感兴趣 => 表单有一个dirtystatus 女巫,您可以使用它启用/禁用保存按钮。
    因此,如果启用该按钮,您肯定会发生一些变化。
    如果您需要知道“克隆”对象所需的确切更改,以便检查。
    但我认为表单对象解决了您在未进行任何更改时无法按下按钮的问题。

    希望对你有所帮助。

    【讨论】:

    • 我必须知道确切的变化。我已经在使用form 绑定(请参阅上面的editPersonDialog 查看代码),因此它会处理一个中间对象,直到用户保存表单。但是当 viewmodel 属性对象已经更新时,我需要在我的 savePerson 方法中进行比较。我忘记了关于通过引用复制的要点(尽管我来自 C#,它是相同的......)所以我将克隆我的对象。我将实现我自己的clone() 方法,因为似乎使用IClonable 不被视为最佳实践。谢谢chillword,它帮了很多忙;)
    • 也许你可以在保存后更新表单对象?将表单作为 bindingparam 传递,就像这个 personen 是干净的,并且更改在表单对象中
    • 确实这可能是一个解决方案,但是这样做我无法将我的对象保存到数据库中,假设newPerson 是我的绑定参数,试图直接保存它(personManager.update(newPerson))引发unknown entity 异常。在保存 (setPerson(newPerson); personManager.update(person)) 之前将 newPerson 对象放入 person 对象会引发 nested form 异常。
    • 当然,从 ZK8 开始,这可能是可能的(因为代理也是对象类的)但是现在,您需要在保存之前遍历字段并自己更新人员。如果您需要对 DB 进行版本控制,您可以查看 hibernate.org/orm/envers
    • 好的,我明白了。现在一切都很好,感谢您的耐心等待。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-11-16
    • 2019-03-20
    • 1970-01-01
    • 2016-06-29
    • 2018-11-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多