为什么在添加 child 记录时未定义 session.getSaveBatch() - Ext 5.1.1

Why session.getSaveBatch() is undefined when child record was added - Ext 5.1.1

标题说明了一切,详情如下。

我有两个相关模型,用户和角色。

用户的角色定义为:

Ext.define('App.model.security.User', {
    extend: 'App.model.Base',

    entityName: 'User',

    fields: [
        { name: 'id' },
        { name: 'email'},
        { name: 'name'},
        { name: 'enabled', type: 'bool'}
    ],

    manyToMany: 'Role'
});

然后我有一个用户网格和一个用于编辑用户数据(包括他的角色)的表单。

问题是,当我稍后调用 session.getSaveBatch() returns undefined 尝试向用户添加或删除角色时,我无法启动批处理以将修改发送到服务器。

我该如何解决这个问题?

嗯,看了很多之后发现Ext至少在5.1.1上不会保存两个模型之间变化的关系。 我不得不通过在左侧模型上放置一个默认值为 false 的附加字段(我将其命名为 isDirty)来解决此问题,并将其设置为 true 以强制会话使用 getSaveBatch 将更新发送到服务器。

稍后我将深入研究代码,以编写对 BatchVisitor 或自定义 BatchVisitor class 的覆盖,以允许自动保存关联。

请注意,只有当您只想保存两个模型之间的关联时才会发生这种情况,并且如果您还修改了其中一个相关实体,那么关联将在保存批处理时发送。

这很有趣,通过解决这个简单的问题,我学到了很多关于 Ext 的知识。

我遇到的解决方案是重写 BatchVisitor class 以对从 Session class 的私有方法 visitData 引发的事件 onCleanRecord 使用事件处理程序 class。

因此,对于每条记录,我在矩阵中查找左侧实体,如果有变化,则调用 onDirtyRecord 的处理程序,该处理程序在 BatchVisitor 原始 class.

上定义

代码:

Ext.define('Ext.overrides.data.session.BatchVisitor', {
    override: 'Ext.data.session.BatchVisitor',

    onCleanRecord: function (record) {
        var matrices = record.session.matrices
            bucket = null,
            ops = [],
            recordId = record.id,
            className = record.$className;

        // Before anything I check that the record does not exists in the bucket
        // If it exists then any change on matrices will be considered (so leave)
        try {
            bucket = this.map[record.$className];
            ops.concat(bucket.create || [], bucket.destroy || [], bucket.update || []);

            var found = ops.findIndex(function (element, index, array) {
                if (element.id === recordId) {
                    return true;
                }
            });

            if (found != -1) {
                return;
            }

        }
        catch (e) {
            // Do nothing
        }

        // Now I look for changes on matrices
        for (name in matrices) {
            matrix = matrices[name].left;

            if (className === matrix.role.cls.$className) {
                slices = matrix.slices;

                for (id in slices) {
                    slice = slices[id];
                    members = slice.members;

                    for (id2 in members) {
                        id1 = members[id2][0]; // This is left side id, right side is index 1
                        state = members[id2][2];

                        if (id1 !== recordId) { // Not left side => leave
                            break;
                        }

                        if (state) { // Association changed
                            this.onDirtyRecord(record);
                            // Same case as above now it exists in the bucket (so leave)
                            return;
                        }
                    }
                }
            }
        }
    }
});

它非常适合我的需要,可能对其他人来说不是最佳解决方案,但无论如何可以作为一个起点。

最后,如果还不清楚的话,这样做是为了让方法 getSaveBatch 能够检测关系的变化。