2012-03-26 3 views
8

У меня есть две модели данных: Writer.AttributValeur и Writer.Produit.ExtJS, магазин, HasMany - BelongsTo и процесс обновления: howto?

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

Проблема заключается в том, когда я вставляю в этой области «attributs» в Writer.AttributValeur, как это:

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

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

ответ

8

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

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

Вы что, ? Также вы можете отметить фрагменты, которые были опущены из решения, размещенного в потоке Sencha? – dbrin

+0

Вот еще один интересный подход с формами: http://stackoverflow.com/a/9891694/834424 – dbrin

+0

Я работаю над этим 20/7, поэтому я отредактировал решение, потому что мое другое решение не сработало при вставке новых записей. Теперь (1) все работает нормально (2) он вызывает функцию родителя (= исходная функция 'getRecordData()' sencha), которая более безопасна, умнее и, вероятно, останется совместимой в долгосрочной перспективе (3), она намного короче, понять –

0

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

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

+0

Я уже пробовал: ничего не происходит. Пытался ставить 'setDirty()' везде, кроме исключений, все время (= плохое место), за исключением 'this.formDst.getRecord(). SetDirty();'. –

+0

Я нашел очень интересный вопрос с хорошими ответами здесь http://www.sencha.com/forum/showthread.php?141957-Saving-objects-that-are-linked-hasMany-relation-with-a-single -Хранить. Случается, что ничего не сделано для сохранения «автоматически» вложенных ассоциаций, что нелогично: можно загружать «автоматически» вложенные ассоциации, но не сохранять их «автоматически» ... Не работает с ExtJs4.0: ' Uncaught TypeError: Object [object Object] не имеет метода getData''. Черт возьми, х 2! Не работает с ExtJS 4.1: 'Uncaught TypeError: Невозможно прочитать свойство 'persist' undefined'. –

+0

(Я пытался добавить последнее решение с ** классом 'Ext.data.writer.DeepJson' **. Не работает. Я попробую с другим образцом, может быть, это сработает, только Бог знает ... –

0

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

+0

Именно поэтому я отправляю решение, которое помогает сообществу. В любом случае, если вложенный «Измененные» записи не публикуются с основной записью, они нарушают все принципы KISS + DRY. –

+0

Я согласен, я всегда чувствовал, что ассоциации моделей в 4.0 были в лучшем случае испечены. – dbrin

1

мне понравилось простое решение, поэтому я также добавил 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; 
} 

});

+0

Спасибо, собирался добавить это в себя. – dubvfan87