ExtJS, store, HasMany - BelongsTo and update process: howto?

12,376

i liked the simple solution so i also added belongsTo Support:

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

});

Share:
12,376
Admin
Author by

Admin

Updated on June 19, 2022

Comments

  • Admin
    Admin over 1 year

    I have two data models: Writer.AttributValeur and Writer.Produit.

    Writer.Produit has HasMany / BelongsTo relationship with Writer.AttributValeur.

    Thus the definition is like this:

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

    Now, when I read the file, asking for "Produits", there's an AJAX answer that works perfectly:

    AJAX answer that works perfectly

    And in each "row", there are many Writer.AttributValeur (I've aliased them as "attributs" see picture):

    many Writer.AttributValeur

    The problem is when I insert a Writer.AttributValeur in this "attributs" field, like this:

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

    It works perfectly but when I call store.sync() nothing happens. So I mark by hand the record as dirty:

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

    Now it's sent, but the attributs are not sent! See:

    Showing that the attributs are not sent

    How shall I do to "add" this into the update process?

  • Admin
    Admin over 11 years
    I've already tried that: nothing happens. Tried to put setDirty() everywhere but exceptions all the time (= bad place) except with this.formDst.getRecord().setDirty();.
  • Admin
    Admin over 11 years
    I've found a very interesting question with nice answers here sencha.com/forum/…. It happens that there's nothing done to save "automatically" nested associations, which is not logical: it's possible to load "automatically" nested associations, but not to save them "automatically"... Doesn't work with ExtJs4.0: Uncaught TypeError: Object [object Object] has no method 'getData'. Damn it x 2! Doesn't work with ExtJS 4.1: Uncaught TypeError: Cannot read property 'persist' of undefined.
  • Admin
    Admin over 11 years
    (I was trying to add the latest solution with Ext.data.writer.DeepJson class. Doesn't work. I'll try with other sample, maybe that will work, only God knows...
  • sha
    sha over 11 years
    Well.. if it's a bug (omission) from standard ExtJs logic - I would suggest expanding standard writer by including this additional attributes.
  • Admin
    Admin over 11 years
    Exactly. That's why I'm posting a solution that works to help the community. Anyway, if nested "modified" records aren't posted with the main record, it break the whole KISS + DRY principles.
  • dbrin
    dbrin over 11 years
    I agree, I've always felt that the model associations in 4.0 were half baked at best.
  • dubvfan87
    dubvfan87 over 10 years
    Thanks, was about to add this in myself.