2013-08-16 33 views
10

Model.save() yanıt kümesindeki sonuçların, sunucuda bulunan güncel verilere rağmen neden güncelleştirilmiş ilişkili verileri düzgün bir şekilde geri göndermediğini merak ediyorum cevabı ...ExtJS 4.1 - Model.Save() Yanıtında İlişkilendirilen Veriler Yanıtı

Örnek Modeli & Mağaza Tanımı: tek model ile proxy READ istek, ve ilişkili verilere

Ext.define("App.model.test.Parent",{ 
    extend: 'Ext.data.Model', 
    requires: ['App.model.test.Child'], 
    fields: [ 
      {name: 'id', type: 'int' }, 
      {name: 'name', type: 'string'}, 
      {name: 'kids', type: 'auto', defaultValue: []} 
    ], 
    idProperty: 'id', 

    hasMany: [{ 
      foreignKey: 'parent_id', 
      model: 'App.model.test.Child', 
      associationKey: 'kids', 
      name: 'getKids' 
    }], 

    proxy: { 
     type: 'ajax', 
     api : { 
      create: '/service/test/create/format/json', 
      read : '/service/test/read/format/json', 
      update : '/service/test/update/format/json' 
     }, 

     reader: { 
      idProperty  : 'id', 
      type   : 'json', 
      root   : 'data',   
      successProperty : 'success',  
      messageProperty : 'message' 
     }, 

     writer: { 
      type   : 'json', 
      writeAllFields : true 
     } 
    } 
}); 

Ext.define("App.model.test.Child",{ 
    extend: 'Ext.data.Model', 
    fields: [ 
     {name: 'id', type: 'int' }, 
     {name: 'name', type: 'string'}, 
     {name: 'parent_id', type: 'int'} 
    ] 
}); 

Ext.define("App.store.test.Simpson",{ 
    storeId: 'TheSimpsons', 
    extend: 'Ext.data.Store', 
    model : 'App.model.test.Parent', 
    autoLoad: true, 
    autoSync: false 
}); 

uygulama sunucusu yanıt. Hepsi bu hunky dory!

Sunucu Yanıtı İsteği OKUYUN için

{ 
"data":{ 
    "id":1, 
    "name":"Homer Simpson", 
    "children":{ 
     "1":{ 
      "id":1, 
      "name":"Bart Simpson" 
     }, 
     "2":{ 
      "id":2, 
      "name":"Lisa Simpson" 
     }, 
     "3":{ 
      "id":3, 
      "name":"Maggie Simpson" 
     } 
    } 
}, 
"success":true, 
"message":null 
} 

Bugüne kadar her şey ... plana göre çalışmaktadır

store = Ext.create("App.store.test.Simpson"); 
homer = store.getById(1); 
kids = homer.getKids().getRange(); 
console.log("The Simpson Kids", kids); // [>constructor, >constructor, >constructor] 

İSTENMEYEN DAVRANIŞ KAYDET İLE BAŞLIYOR VE GÜNCELLEME İSTEKLERİ

İşte

/** Server UPDATE Response */ 
{ 
"data":{ 
    "id":1, 
    "name":"SAVED Homer Simpson", 
    "kids":[{ 
     "id":1, 
     "name":"SAVED Bart Simpson", 
     "parent_id":1 
    },{ 
     "id":2, 
     "name":"SAVED Lisa Simpson", 
     "parent_id":1 
    },{ 
     "id":3, 
     "name":"SAVED Maggie Simpson", 
     "parent_id":1 
    }] 
}, 
"success":true, 
"message":null 
} 


/** Will call proxy UPDATE, response is above */ 
homer.save({ 
    success: function(rec, op){ 
     var savedRec = op.getRecords().pop(), 
      kidNames = ''; 
     console.log(savedRec.get('name')); // SAVED Homer Simpson = CORRECT! 
     Ext.each(savedRec.getKids().getRange(), function(kid){ 
      kidNames += kid.get('name') + ", "; 
     }); 
     console.log(kids); 
     //Outputs: Bart Simpson, Lisa Simpson, Maggie Simpson = WRONG!! 
    } 
}) 

Ben sunucu oluşturulan Derneği Store tarafından döndürülen kaydının incelenmesi (yani, getKidsStore) içerdiği kayıtları orijinal olduğunu fark ... GÜNCELLEME İsteği benim test yanıttır kayıtlar, yani adında "KAYDEDİLMEDİ". Ancak, döndürülen kaydın kids özelliği, DOES gerçekten doğru verileri içerir.

Sorunu doğru bir şekilde anlarsam, Ext.data.reader.Reader'un ilişkili deposu, .save() yanıtında bulunan ilişkili verilerle doğru şekilde güncelleştirmemesidir. Eğer öyleyse, bence, bu, store.load() isteğini işleyen okuyucuyla aynı davranışı bekleyeceğinden ve oluşturulacak ilişki depolarını doldurmaya başladığından çok kasıtsızdır.

Birisi, peşinde olduğum davranışa ulaşmada beni doğru yöne yönlendirebilir mi?

Sorumluluk Reddi: Aynı soru soruldu: ExtJs 4 - Load nested data on record save ama yanıt vermeden. Ben .. benim sorum biraz daha kapsamlı olmak nasıl bir duygu

DÜZENLEME

: http://www.sencha.com/forum/showthread.php?270336-Associated-Data-in-Model.save()-Response

DÜZENLEME (8/23/13): Ben yeniden ben Sencha'sı forumlarında üzerinde bu soruyu gönderdiniz sorunu buldum, daha doğrusu karışıklıkExt.data.Operation arasında getRecords() yöntemi yatıyor bu bir TAM örnekle yazıyı yanı sıra ek bulgular ...

cevap

6

yazdı. Bu yöntem döndürür "işlemin başlangıçta yapılandırıldıktan sonra belirli bir noktada vekil bu verileri değiştirebilir, ancak işlemin başlangıçta yapılandırılmış kayıtları iade edilir." Belgelere göre.

Bu, döndürülen kayıt gerçekten güncelleştirildiği için IMO'yu oldukça kafa karıştırıcıdır, ancak oluşturulan ilişki deposu ve dolayısıyla ilişkilendirilmiş veriler değildir! Bu benim karışıklığa neden olan şey, kayıt, uygulama sunucusundan güncellenmiş verileri içerdiği halde ortaya çıktı, ancak durum böyle değildi. yanıttan TAMAMEN güncellenmiş verileri elde benim basit zihin yardım etmek amacıyla

, ben Ext.data.Operation sınıfa bir yöntem eklemiş ... Sadece bu yöntemi yazdım ve daha sağlamaktan daha test etmedim aradığım işlevsellik, bu yüzden kendi sorumluluğunuzda kullanın!

ben store.sync (demiyorlar lütfen unutmayın)

..., daha doğrusu bir model örneğini ve benim Resultset genellikle sadece şimdiye kadar tek bir kayıt içerecek şekilde, model.save() yöntemini çağırın
Ext.override(Ext.data.Operation,{ 
    getSavedRecord: function(){ 
     var me = this, // operation 
      resultSet = me.getResultSet(); 

     if(resultSet.records){ 
      return resultSet.records[0]; 
     }else{ 
      throw "[Ext.data.Operation] EXCEPTION: resultSet contains no records!"; 
     } 

    } 
}); 

Şimdi ... Düzen 12/10/13

// Get the unsaved data 
store = Ext.create('App.store.test.Simpson'); 
homer = store.getById(1); 
unsavedChildren = ''; 

Ext.each(homer.getKids().getRange(), function(kid){ 
    unsavedChildren += kid.get('name') + ","; 
}); 

console.log(unsavedChildren); // Bart Simpson, Lisa Simpson, Maggie Simpson 

// Invokes the UPDATE Method on the proxy 
// See original post for server response 
home.save({ 
    success: function(rec, op){ 
     var savedRecord = op.getSavedRecord(), // the magic! /sarcasm 
      savedKids = ''; 

     Ext.each(savedRecord.getKids().getRange(), function(kid){ 
      savedKids += kid.get('name') + ','; 
     }); 

     console.log("Saved Children", savedKids); 

     /** Output is now Correct!! 
      SAVED Bart Simpson, SAVED Lisa Simpson, SAVED Maggie Simpson 
      */ 
    } 
}); 

peşinde olduğum işlevselliği elde edebilmek duyuyorum Ben de bir kayıt güncelleme kolları updateTo denilen Ext.data.Model için bir yöntem eklendi sağlanan kayıt, ayrıca dernekleri ele alır. Bunu, yukarıdaki getSavedRecord yöntemiyle birlikte kullanıyorum. Lütfen bu, benim uygulamamda kullanmadığımdan belongsTo derneklerini işlemez, ancak bu işlevin eklenmesinin kolay olacağını lütfen unutmayın.

/** 
* Provides a means to update to the provided model, including any associated data 
* @param {Ext.data.Model} model The model instance to update to. Must have the same modelName as the current model 
* @return {Ext.data.Model} The updated model 
*/ 
updateTo: function(model){ 
    var me = this, 
    that = model, 
    associations = me.associations.getRange(); 

    if(me.modelName !== that.modelName) 
    throw TypeError("updateTo requires a model of the same type as the current instance ("+ me.modelName +"). " + that.modelName + " provided."); 

    // First just update the model fields and values 
    me.set(that.getData()); 

    // Now update associations 
    Ext.each(associations, function(assoc){ 
    switch(assoc.type){ 
     /** 
     * hasOne associations exist on the current model (me) as an instance of the associated model. 
     * This instance, and therefore the association, can be updated by retrieving the instance and 
     * invoking the "set" method, feeding it the updated data from the provided model. 
     */ 
     case "hasOne": 
      var instanceName = assoc.instanceName, 
       currentInstance = me[instanceName], 
       updatedInstance = that[instanceName]; 

      // Update the current model's hasOne instance with data from the provided model 
      currentInstance.set(updatedInstance.getData()); 

      break; 

     /** 
     * hasMany associations operate from a store, so we need to retrieve the updated association 
     * data from the provided model (that) and feed it into the current model's (me) assocStore 
     */ 
     case "hasMany": 
      var assocStore = me[assoc.storeName], 
       getter  = assoc.name, 
       newData = that[getter]().getRange(); 

      // Update the current model's hasMany association store with data from the provided model's hasMany store 
      assocStore.loadData(newData); 
      break; 

     // If for some reason a bogus association type comes through, throw a type error 
     // At this time I have no belongsTo associations in my application, so this TypeError 
     // may one day appear if I decide to implement them. 
     default: 
      throw TypeError("updateTo does not know how to handle association type: " + assoc.type); 
      break; 
    } 
    }); 

    // Commit these changes 
    me.commit(); 

    return me; 
} 

Böylece temelde (bu teorik Sipariş denetleyicisi olacaktır) böyle bir şey yapmak

doSaveOrder: function(order){ 
    var me = this,      // order controller 
     orderStore = me.getOrderStore(); // magic method 

    // Save request 
    order.save({ 
     scope: me, 
     success: function(responseRecord, operation){ 
      // note: responseRecord does not have updated associations, as per post 
      var serverRecord = operation.getSavedRecord(), 
       storeRecord = orderStore.getById(order.getId()); 

      switch(operation.action){ 
       case 'create': 
        // Add the new record to the client store 
        orderStore.add(serverRecord); 
       break; 

       case 'update': 
        // Update existing record, AND associations, included in server response 
        storeRecord.updateTo(serverRecord); 
       break; 
      } 
     } 
    }); 
} 

Bunun benim gibi karıştı birisi yardımcı olur umarım!

3

Tamamen size katılıyorum. Gerçekten garip davranışlar. Kayıttaki ilişki deposunu güncellemelidir. Bu ben bu konuda (! Temelde sadece okuyucu aracılığıyla tepkisini çalıştırın) etrafında var nasıl: Kimlik alanına bir değer varsa

success: function(record, operation) { 
    var newRecord= me.getMyModel().getProxy().reader.read(operation.response).records[0]; 
} 
+0

İyi bir çözüm! Herhangi bir nedenden dolayı, Mağazanın, Proxy'nin okuma işlemini Model'den manuel olarak başlatırken her zaman güncellenmediğini fark ettim ... Bu nedenle, model sınıfını, sağlanan bir örneğe güncelleştirmeyi sağlayan Model sınıfında 'updateTo' ekledim İlişkilendirme mağazaları dahil olmak üzere kayıt (sunucunun yanıtından alındı). Aynı fikir, sadece farklı yaklaşım :) –

+0

Daha açık/yardımcı olmak için 'updateTo' yöntemini yanıtıma ekledim. –

-1

sonra ExtJS hep güncellemeyi arayacak. Kimlik alanınıza herhangi bir değer yazmazsanız veya null olarak ayarlarsanız, oluşturmayı çağırmalısınız. Sanırım mevcut bir kayıtla kaydetmeyi deniyorsunuz, böylece her zaman güncellemeyi arayacak. Bu istenen bir davranış.

+1

Sorunun, oluşturma/güncelleştirme istekleriyle bir ilgisi yok ... yalnızca ilişkili verileri döndürme ile ilgili olması gerekiyor ve ExtJS, mağaza kayıtlarını buna göre güncelleştiriyor, bu da hiç gösterilmiyor ... Kayıt, sunucudan tamamen yeniden yüklenmeli (yararsız bir gidiş gelişi zorlamalıdır) veya sunucu cevabında sağlanan veriler kullanılarak manuel olarak güncellenmelidir. –