2012-03-26 9 views
8

Ho due modelli di dati: Writer.AttributValeur e Writer.Produit.ExtJS, store, HasMany - BelongsTo e aggiornamento processo: howto?

Writer.Produit ha HasMany/BelongsTo rapporto con Writer.AttributValeur.

Così la definizione è come questo:

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

Ora, quando ho letto il file, chiedendo "Produits", non c'è una risposta AJAX che funziona perfettamente:

AJAX answer that works perfectly

E in ogni "riga", ci sono molti Writer.AttributValeur (li ho alias come "attributi" vedi immagine):

many Writer.AttributValeur

Il problema è quando inserisco un Writer.AttributValeur in questo campo "attributs", in questo modo:

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

Funziona perfettamente, ma quando chiamo store.sync() non succede nulla. Così ho marchio da parte il record come dirty:

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

ora è inviato, ma il attributs non vengono inviati! Vedere:

Showing that the attributs are not sent

Come farò a "aggiungere" questo nel processo di aggiornamento?

risposta

8

Ecco la roba di override:

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

Ed ecco un esempio di come la sto usando:

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

E quando aggiungo un record annidato ecco come faccio questo con attributs che è un'associazione OneMany (vedi la mia domanda).E 'importante notare che ho impostato sporchi tutti annidati record in modo che io sono sicuro di essere inviati:

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(); 
+0

Hai fatto davvero che funzioni ? Puoi anche notare i pezzi che sono stati omessi dalla soluzione pubblicata sul thread Sencha? – dbrin

+0

Ecco un altro approccio interessante con i moduli: http://stackoverflow.com/a/9891694/834424 – dbrin

+0

Ci ho lavorato 20/7, quindi ho modificato la soluzione, perché l'altra soluzione non funzionava quando inserivo nuovi record. Ora (1) tutto funziona bene (2) chiama la funzione genitore (= la funzione 'getRecordData()' originale di sencha), che è più sicura, più intelligente e probabilmente rimarrà compatibile nel lungo periodo (3) è molto più breve quindi più facile capire –

0

Dai documenti sencha: sembra che sia necessario chiamare la sincronizzazione su form.getRecord().attributs() e non sul record principale. Puoi provarlo?

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

+0

L'ho già provato: non succede nulla. Ho cercato di mettere 'setDirty()' ovunque tranne le eccezioni (= luogo errato) tranne con 'this.formDst.getRecord(). SetDirty();'. –

+0

Ho trovato una domanda molto interessante con belle risposte qui http://www.sencha.com/forum/showthread.php?141957-Saving-objects-that-are-linked-hasMany-relation-with-a-single -Negozio. Succede che non c'è nulla da fare per salvare associazioni "nidificate" automaticamente, il che non è logico: è possibile caricare associazioni "nidificate" automaticamente, ma non salvarle "automaticamente" ... Non funziona con ExtJs4.0: ' Uncaught TypeError: Object [object Object] non ha alcun metodo 'getData''. Dannazione x 2! Non funziona con ExtJS 4.1: 'Uncaught TypeError: Impossibile leggere la proprietà 'persist' di undefined'. –

+0

(Stavo cercando di aggiungere l'ultima soluzione con la classe ** 'Ext.data.writer.DeepJson' **. Non funziona. Proverò con un altro esempio, forse funzionerà, solo Dio lo sa ... –

0

Questa funzione non è supportata in 4.0x e non è ancora sulla strada funzione per 4.1 per quanto ne so. Ci sono stati alcuni tentativi di risoluzione tuttavia, si veda questa discussione: http://www.sencha.com/forum/showthread.php?141957-Saving-objects-that-are-linked-hasMany-relation-with-a-single-Store

Anche un altro approccio interessante con forme: https://stackoverflow.com/a/9891694/834424 da Jamie Sutherland

+0

Esattamente. Ecco perché sto pubblicando una soluzione che funziona per aiutare la comunità. I record "modificati" non sono registrati con il record principale, ma infrangono tutti i principi di KISS + DRY –

+0

Sono d'accordo, ho sempre pensato che le associazioni di modelli in 4.0 fossero metà cotte al meglio – dbrin

1

Mi è piaciuta la soluzione più semplice così ho anche aggiunto belongsTo Supporto:

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

Grazie, stava per aggiungere questo in me stesso. – dubvfan87