2012-03-26 6 views
8

Ich habe zwei Datenmodelle: Writer.AttributValeur und Writer.Produit.ExtJS, Geschäft, HasMany - BelongsTo und Update-Prozess: howto?

Writer.Produit hat HasMany/BelongsTo Beziehung mit Writer.AttributValeur.

So die Definition wie folgt lautet:

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

Nun, wenn ich die Datei lesen und bat um "Produits", gibt es eine AJAX Antwort, die perfekt funktioniert:

AJAX answer that works perfectly

Und in jeder "Zeile" gibt es viele Writer.AttributValeur (ich habe sie als "attributs" aliased) siehe Bild):

many Writer.AttributValeur

Das Problem ist, wenn ich ein Writer.AttributValeur in diesem "attributs" Feld einfügen, wie folgt aus:

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

Es funktioniert perfekt, aber wenn ich store.sync() nichts passiert nennen. So markieren ich von Hand den Rekord als dirty:

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

Jetzt ist es geschickt, aber die attributs werden nicht gesendet! Siehe:

Showing that the attributs are not sent

Wie soll ich tun, um "add" diese in den Update-Prozess?

Antwort

8

Hier ist die Überschreibung Zeug:

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

Und hier ist ein Beispiel wie ich es verwende:

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

Und wenn ich einen verschachtelten Datensatz hinzufügen Hier ist, wie ich das mit attributs, die OneToMany Association ist (siehe meine Frage).Es ist wichtig zu beachten, dass ich Schmutzige alle verschachtelten Rekorde aufgestellt, so dass ich sicher bin, sie sind geschickt:

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

Hast du sehr, dass es funktioniert Können Sie auch Teile notieren, die in der Lösung, die auf dem Sencha-Thread gepostet wurde, weggelassen wurden? – dbrin

+0

Hier ist ein weiterer interessanter Ansatz mit Formularen: http://stackoverflow.com/a/9891694/834424 – dbrin

+0

Ich habe am 20/7 daran gearbeitet, also habe ich die Lösung bearbeitet, weil meine andere Lösung beim Einfügen neuer Datensätze nicht funktioniert hat. Jetzt (1) funktioniert alles gut (2) es ruft die Funktion des Elternteils auf (= Senchas ursprüngliche 'getRecordData()' Funktion), die sicherer, schlauer ist und wahrscheinlich auf lange Sicht kompatibel bleiben wird (3) sie ist viel kürzer und einfacher verstehe –

0

Von der Sencha-Dokumentation - sieht so aus, als müssten Sie die Synchronisierung unter form.getRecord().attributs() aufrufen und nicht im Hauptdatensatz. Kannst du das versuchen?

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

+0

Ich habe das schon probiert: nichts passiert. Versucht, 'setDirty()' überall außer Ausnahmen die ganze Zeit (= schlechte Stelle) außer mit 'this.formDst.getRecord(). SetDirty();'. –

+0

Ich habe eine sehr interessante Frage mit netten Antworten hier http://www.sencha.com/forum/showthread.php?141957-Saving-objects-that-are-linked-hasMany-relation-with-a-single gefunden -Geschäft. Es passiert, dass nichts getan wird, um "automatisch" verschachtelte Assoziationen zu speichern, was nicht logisch ist: Es ist möglich, "automatisch" verschachtelte Assoziationen zu laden, aber nicht "automatisch" zu speichern ... Funktioniert nicht mit ExtJs4.0: ' Uncaught TypeError: Objekt [Objekt Objekt] hat keine Methode 'getData''. Verdammt 2x 2! Funktioniert nicht mit ExtJS 4.1: 'Uncaught TypeError: Die Eigenschaft 'persist' von undefined kann nicht gelesen werden. –

+0

(Ich habe versucht, die neueste Lösung mit ** 'Ext.data.writer.DeepJson' ** Klasse hinzuzufügen. Funktioniert nicht. Ich werde mit anderen Probe versuchen, vielleicht wird das funktionieren, nur Gott weiß ... –

0

Diese Funktion wird nicht in 4.0x unterstützt und ist noch nicht auf dem Feature Weg für 4.1 soweit ich weiß. Es wurden jedoch bei einer Auflösung einige Versuche unternommen worden, dieses Thema finden Sie unter: http://www.sencha.com/forum/showthread.php?141957-Saving-objects-that-are-linked-hasMany-relation-with-a-single-Store

Auch ein weiterer interessanter Ansatz mit Formen: https://stackoverflow.com/a/9891694/834424 von Jamie Sutherland

+0

Genau. Deshalb posten ich eine Lösung, die der Gemeinde hilft. Jedenfalls, wenn verschachtelt "modifizierte" Datensätze werden nicht mit dem Hauptdatensatz gepostet, es bricht die gesamten KISS + DRY Prinzipien. –

+0

Ich stimme zu, ich habe immer gefühlt, dass die Modellassoziationen in 4.0 bestenfalls halb gebacken waren. – dbrin

1

Ich möchte die einfache Lösung, so auch ich belongsTo Unterstützung hinzugefügt:

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

Danke, war im Begriff, dies in mir hinzuzufügen. – dubvfan87

Verwandte Themen