ExtJS, store, HasMany - принадлежит и процесс обновления: как? - PullRequest
8 голосов
/ 26 марта 2012

У меня есть две модели данных: Writer.AttributValeur и Writer.Produit.

Writer.Produit имеет HasMany / BelongsTo отношения с Writer.AttributValeur.

Таким образом, определение выглядит так:

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'
        }
    }
});

Теперь, когда я читаю файл с вопросом «Produits», есть ответ AJAX, который отлично работает:

AJAX answer that works perfectly

И в каждой «строке» есть много Writer.AttributValeur (я назвал их как «атрибуты», см. Рисунок):

many Writer.AttributValeur

Проблема в том, что я вставляю Writer.AttributValeur в это поле "attributs", например:

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

Работает отлично, но когда я звоню store.sync(), ничего не происходит. Поэтому я отмечаю от руки запись как dirty:

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

Сейчас оно отправлено, но attributs не отправлено! См:

Showing that the attributs are not sent

Как мне сделать, чтобы «добавить» это в процесс обновления?

Ответы [ 4 ]

8 голосов
/ 27 марта 2012

Вот переопределение:

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 (см. Мой вопрос). Важно отметить, что я установил Dirty все вложенные записи, так что я уверен, что они отправлены:

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();
1 голос
/ 23 ноября 2012

Мне понравилось простое решение, поэтому я также добавил, что для поддержки:

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;
}

});

0 голосов
/ 27 марта 2012

Эта функция не поддерживается в 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 от Джейми Сазерленда

0 голосов
/ 26 марта 2012

Из документов Sencha - похоже, вам нужно вызвать синхронизацию на form.getRecord().attributs(), а не на основной записи.Вы можете попробовать это?

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

...