【问题标题】:ExtJS, store, HasMany - BelongsTo and update process: howto?ExtJS、商店、HasMany - BelongsTo 和更新过程:howto?
【发布时间】:2012-11-23 15:04:30
【问题描述】:

我有两个数据模型:Writer.AttributValeurWriter.Produit

Writer.ProduitWriter.AttributValeurHasMany / BelongsTo 关系。

所以定义是这样的:

Ext.define('Writer.AttributValeur', {
    extend: 'Ext.data.Model',
    fields: [{
            name: 'id',
            type: 'int',
            useNull: true
        },  
        'description',
        'val'
    ],  
    belongsTo: 'Writer.Produit'
});

Ext.define('Writer.Produit', {
    extend: 'Ext.data.Model',
    fields: [{
            name: 'id',
            type: 'int',
            useNull: true
        },  
        'titre',
        'description'
    ],
    hasMany: {
        model: 'Writer.AttributValeur',
        name: 'attributs'
    }   
});

var store = Ext.create('Ext.data.Store', {
    model: 'Writer.Produit',
    autoLoad: true,
    autoSync: true,
    proxy: {
        type: 'ajax',
        api: {
            read: 'json/liste_view/',
            create:  'json/item/?mode=create',
            update:  'json/item/?mode=update',
            destroy: 'json/item/?mode=destroy'
        },
        reader: {
            type: 'json',
            successProperty: 'success',
            root: 'data',
            messageProperty: 'message'
        },
        writer: {
            type: 'json',
            writeAllFields: true,
            root: 'data'
        }
    }
});

现在,当我阅读文件并询问“产品”时,有一个完美运行的 AJAX 答案:

并且在每一“行”中,有很多Writer.AttributValeur(我将它们别名为“属性”见图):

问题是当我在此“attributs”字段中插入Writer.AttributValeur 时,如下所示:

form.getRecord().attributs().add(newrecord);

它工作得很好,但是当我打电话给store.sync() 时没有任何反应。所以我手动将记录标记为dirty

form.getRecord().attributs().add(newrecord);
form.getRecord().setDirty();
form.getRecord().store.sync();

现在已发送,但attributs 未发送!见:

我应该如何将它“添加”到更新过程中?

【问题讨论】:

    标签: extjs extjs4


    【解决方案1】:

    这里是覆盖的东西:

    Ext.data.writer.Json.override({
      {*/*
         * This function overrides the default implementation of
         * json writer. Any hasMany relationships will be submitted
         * as nested objects
         */*}
        getRecordData: function(record) {
            var me = this, i, association, childStore, data = {}; 
            data = me.callParent([record]);
    
            /* Iterate over all the hasMany associations */
            for (i = 0; i < record.associations.length; i++) {
                association = record.associations.get(i);
                if (association.type == 'hasMany')  {
                    data[association.name] = []; 
                    childStore = eval('record.'+association.name+'()');
    
                    //Iterate over all the children in the current association
                    childStore.each(function(childRecord) {
    
                        //Recursively get the record data for children (depth first)
                        var childData = this.getRecordData.call(this, childRecord);
                        if (childRecord.dirty | childRecord.phantom | (childData != null)){
                            data[association.name].push(childData);
                            record.setDirty();
                        }   
                    }, me);
                }   
            }   
            return data;
        }   
    }); 
    

    下面是我如何使用它的示例:

    var store = Ext.create('Ext.data.Store', {
        model: 'Writer.Produit',
        autoLoad: true,
        autoSync: true,
        proxy: {
            type: 'ajax',
            api: {
                read: 'json/liste_view/',
                create:  'json/item/?mode=create',
                update:  'json/item/?mode=update',
                destroy: 'json/item/?mode=destroy'
            },
            reader: {
                type: 'json',
                successProperty: 'success',
                root: 'data',
                messageProperty: 'message'
            },
            writer: new Ext.data.writer.Json( {
                type: 'json',
                writeAllFields: true,
                root: 'data'
            })
        }
    });
    

    当我添加嵌套记录时,这是我如何使用 attributs 执行此操作的,这是 oneToMany 关联(请参阅我的问题)。请务必注意,我设置了“脏”所有嵌套记录,以便确定它们已发送:

    var rec = this.formDst.getRecord(),
        atts = rec.attributs();
    atts.add(sel);
    for (var i = 0; i <atts.data.items.length; i++) {
        atts.data.items[i].setDirty();
    };
    rec.setDirty();
    rec.store.sync();
    this.close();
    

    【讨论】:

    • 你觉得它有效吗?您还可以注意在 Sencha 线程上发布的解决方案中省略的部分吗?
    • 这是另一种有趣的表单方法:stackoverflow.com/a/9891694/834424
    • 我一直在 20/7 工作,所以我编辑了解决方案,因为我的其他解决方案在插入新记录时不起作用。现在(1)一切正常(2)它调用父函数(= sencha 的原始函数getRecordData() 函数),它更安全、更智能,并且从长远来看可能会保持兼容(3)它更短,因此更容易理解
    • 为什么我保存时 this.writeAllFields 为假?
    • 我建议你把eval('record.'+association.name+'()');改成record[association.name]();
    【解决方案2】:

    我喜欢简单的解决方案,所以我还添加了 belongsTo 支持:

    Ext.data.writer.Json.override({
    getRecordData:function (record) {
    
        var me = this, i, association, childStore, data = {};
        data = me.callParent([record]);
    
        /* Iterate over all the hasMany associations */
        for (i = 0; i < record.associations.length; i++) {
    
            association = record.associations.get(i);
            if (association.type == 'hasMany') {
                data[association.name] = [];
                childStore = eval('record.' + association.name + '()');
    
                //Iterate over all the children in the current association
                childStore.each(function (childRecord) {
    
                    //Recursively get the record data for children (depth first)
                    var childData = this.getRecordData.call(this, childRecord);
                    if (childRecord.dirty | childRecord.phantom | (childData != null)) {
                        data[association.name].push(childData);
                        record.setDirty();
                    }
                }, me);
            }
    
            if(association.type == 'belongsTo') {
    
                // we need ucfirst
                var method = 'get' + association.name.charAt(0).toUpperCase() + association.name.slice(1);
                var childRecord = eval('record.' + method + '()');
                var childData = this.getRecordData.call(this, childRecord);
    
                if (childRecord.dirty | childRecord.phantom | (childData != null)) {
                    data[association.name] = childData;
                    record.setDirty();
                }
    
            }
    
        }
        return data;
    }
    

    });

    【讨论】:

    • 谢谢,正准备自己添加这个。
    【解决方案3】:

    来自 sencha 文档 - 看起来您需要在 form.getRecord().attributs() 而不是主记录上调用同步。可以试试吗?

    http://docs.sencha.com/ext-js/4-0/#!/api/Ext.data.HasManyAssociation

    【讨论】:

    • 我已经尝试过了:没有任何反应。试图将setDirty() 放在任何地方,但始终有例外(= 不好的地方),this.formDst.getRecord().setDirty(); 除外。
    • 我在这里sencha.com/forum/… 发现了一个非常有趣的问题,并提供了很好的答案。碰巧没有做任何事情来保存“自动”嵌套关联,这不合逻辑:可以加载“自动”嵌套关联,但不能“自动”保存它们......不适用于 ExtJs4.0:@ 987654326@。该死的×2!不适用于 ExtJS 4.1:Uncaught TypeError: Cannot read property 'persist' of undefined
    • (我试图用 Ext.data.writer.DeepJson 类添加最新的解决方案。不起作用。我会尝试使用其他示例,也许这会起作用,只有上帝知道...
    • 好吧.. 如果这是标准 ExtJs 逻辑的错误(遗漏) - 我建议通过包含这些附加属性来扩展标准编写器。
    【解决方案4】:

    据我所知,4.0x 不支持此功能,并且尚未在 4.1 的功能路径上。 然而,已经有一些解决方法的尝试,请参阅此线程:http://www.sencha.com/forum/showthread.php?141957-Saving-objects-that-are-linked-hasMany-relation-with-a-single-Store

    还有另一种有趣的表单方法:https://stackoverflow.com/a/9891694/834424 by Jamie Sutherland

    【讨论】:

    • 没错。这就是为什么我要发布一个可以帮助社区的解决方案。无论如何,如果嵌套的“修改”记录没有与主记录一起发布,它会破坏整个 KISS + DRY 原则。
    • 我同意,我一直觉得 4.0 中的模型关联充其量只是半生不熟。
    猜你喜欢
    • 2014-03-11
    • 2013-11-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多