2013-08-16 10 views
10

मुझे उत्सुकता है कि Model.save() प्रतिक्रिया के परिणाम सेट में निहित रिकॉर्ड सर्वर से जुड़े अद्यतन डेटा के बावजूद अपडेट किए गए संबंधित डेटा को ठीक से वापस नहीं करता है प्रतिक्रिया ...ExtJS 4.1 - Model.Save में रिटर्निंग एसोसिएटेड डेटा() प्रतिक्रिया

उदाहरण मॉडल & स्टोर परिभाषा: उसके संबंधित डेटा एक मॉडल के साथ प्रॉक्सी के READ अनुरोध है, और करने के लिए

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

आवेदन सर्वर प्रतिक्रिया। यह सब काम कर रहे हैं डरावनी डोरी!

सर्वर प्रतिक्रिया अनुरोध पढ़ें करने के लिए

{ 
"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 
} 

प्रकार अब तक, सब कुछ योजना के अनुसार काम कर रहा है ...

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

अवांछित व्यवहार बचाने से शुरू होकर अद्यतन अनुरोध

यहाँ अद्यतन अनुरोध के लिए अपने परीक्षण प्रतिक्रिया

/** 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!! 
    } 
}) 

मैं नोटिस कि अगर मैं रिकॉर्ड सर्वर, उत्पन्न एसोसिएशन स्टोर द्वारा लौटाए गए निरीक्षण (यानी, getKidsStore) निहित रिकॉर्ड मूल हो रहा है ... रिकॉर्ड, यानी, उनके नाम पर "सहेजा" नहीं है। kids लौटा रिकॉर्ड की संपत्ति, हालांकि, वास्तव में सही डेटा होता है।

यदि मैं सही ढंग से समस्या को समझता हूं, तो यह है कि Ext.data.reader.Reader.save() प्रतिक्रिया में निहित संबंधित डेटा के साथ संबंधित स्टोर को सही ढंग से अपडेट नहीं करता है। यदि हां, तो मेरी राय में, यह बहुत ही अनजान है क्योंकि मैं पाठक के समान व्यवहार की अपेक्षा करता हूं जो store.load() अनुरोध को संभालता है और जेनरेट किए गए एसोसिएशन स्टोर्स को शुरू करने के लिए पॉप्युलेट करता है।

क्या कोई मुझे उस व्यवहार को प्राप्त करने में सही दिशा में इंगित कर सकता है जिसके बाद मैं हूं?

अस्वीकरण: वही प्रश्न यहां पूछा गया था: ExtJs 4 - Load nested data on record save लेकिन बिना किसी प्रतिक्रिया के। मैं अपने सवाल में थोड़ा और अधिक गहन रूप से लग रहा है ..

संपादित करें: http://www.sencha.com/forum/showthread.php?270336-Associated-Data-in-Model.save()-Response

संपादित करें (8/23/13): मैं फिर से मैं Sencha मंचों पर पर इस प्रश्न पोस्ट किया है पूर्ण उदाहरण के साथ इस पोस्ट के साथ-साथ अतिरिक्त निष्कर्ष ...

उत्तर

6

लिखा था मैं समस्या मिली है, या बल्कि, भ्रमExt.data.Operation की getRecords() विधि में निहित है। यह विधि लौटाती है "ऑपरेशन के आरंभ में कॉन्फ़िगर किए गए रिकॉर्ड वापस लौटाए जाएंगे, हालांकि ऑपरेशन प्रारंभ होने के बाद प्रॉक्सी इन रिकॉर्ड्स के डेटा को संशोधित कर सकता है।" दस्तावेज के अनुसार

यह आईएमओ को भ्रमित करने वाला है, क्योंकि लौटा रिकॉर्ड वास्तव में अपडेट किया गया है, हालांकि जेनरेट एसोसिएशन स्टोर, और इसलिए संबंधित डेटा, नहीं है! यह मेरी भ्रम का कारण बनता है, ऐसा लगता है कि रिकॉर्ड में एप्लिकेशन सर्वर से अपडेट किया गया डेटा था, लेकिन ऐसा नहीं था।

आदेश प्रतिक्रिया से पूरी तरह अद्यतन डेटा प्राप्त करने में मेरी सरल मन सहायता करने के लिए में, मैं Ext.data.Operation वर्ग के लिए एक विधि को शामिल किया है ... मैं तो बस इस विधि में लिखा था और परीक्षण नहीं किया यह सुनिश्चित की तुलना में अधिक कार्यक्षमता जिसे मैं ढूंढ रहा था, इसलिए अपने जोखिम पर उपयोग करें!

कृपया ध्यान रखें कि मैं store.sync (कॉल नहीं करते में रखना), बल्कि मैं एक मॉडल का दृष्टांत और model.save() विधि कहते हैं, तो मेरे ResultSet आम तौर पर केवल कभी एक भी रिकॉर्ड में शामिल है ...

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

    } 
}); 

अब मैं मैं भी Ext.data.Model जो मैं updateTo जो करने के लिए एक रिकॉर्ड को अपडेट करने हैंडल कहा जाता है के लिए एक विधि अतिरिक्त कार्यक्षमता मैं के बाद था प्राप्त करने में सक्षम हूँ ...

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

संपादित 12/10/13 प्रदान किया गया रिकॉर्ड, जो भी संघों को संभालती है। मैं इसे उपरोक्त getSavedRecord विधि के संयोजन के साथ उपयोग करता हूं। कृपया ध्यान दें कि यह किसी भी belongsTo एसोसिएशन को संभाल नहीं करता है क्योंकि मैं उन्हें अपने एप्लिकेशन में उपयोग नहीं करता हूं, लेकिन वह कार्यक्षमता जोड़ना आसान होगा।

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

तो बुनियादी तौर पर मैं कुछ इस तरह करते हैं (यह सैद्धांतिक रूप से आदेश नियंत्रक में होगा)

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

मुझे आशा है कि यह कोई है जो के रूप में मैं था उलझन में था मदद करता है!

3

पूरी तरह से आपसे सहमत हैं। वास्तव में अजीब व्यवहार। इसे रिकॉर्ड पर एसोसिएशन स्टोर अपडेट करना चाहिए। यह मैं कैसे इस मुद्दे (! मूल रूप से सिर्फ पाठक के माध्यम से प्रतिक्रिया चलाने) के चारों ओर हो गया है:

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

अच्छा समाधान! किसी कारण से, मैंने पाया है कि मैन्युअल रूप से मॉडल से प्रॉक्सी के पढ़ने के ऑपरेशन को मैन्युअल रूप से आमंत्रित करते समय स्टोर हमेशा अद्यतन नहीं होता है ... इसलिए मैंने मॉडल क्लास पर एक विधि 'अपडेट टू' जोड़ा, जो प्रदान किए गए उदाहरण को अपडेट करने में संभालता है एसोसिएशन स्टोर्स सहित रिकॉर्ड (सर्वर की प्रतिक्रिया से पुनर्प्राप्त)। वही विचार, बस अलग दृष्टिकोण :) –

+0

अधिक स्पष्ट/सहायक होने के लिए मेरे उत्तर में 'updateTo' विधि जोड़ा गया। –

-1

अपने आईडी क्षेत्र एक मूल्य है तो ExtJS हमेशा अद्यतन कॉल करेंगे। यदि आप अपने आईडी फ़ील्ड में कोई मान नहीं लिखते हैं या इसे शून्य पर सेट करते हैं, तो इसे कॉल करना चाहिए। मुझे लगता है कि आप मौजूदा रिकॉर्ड के साथ सेव कॉल करने की कोशिश कर रहे हैं, इसलिए यह हमेशा अपडेट को कॉल करेगा। यह एक वांछित व्यवहार है।

+1

इस प्रश्न का निर्माण/अद्यतन अनुरोधों के साथ कुछ लेना देना नहीं है ... केवल संबंधित डेटा लौटने और एक्सटीजेएस के अनुसार स्टोर के रिकॉर्ड को अद्यतन करने के साथ ही करना है, जो बिल्कुल भी काम नहीं करता है ... जैसा कि प्रदर्शित किया गया है। रिकॉर्ड को सर्वर से पूरी तरह से पुनः लोड किया जाना चाहिए (बेकार राउंड-ट्रिप को मजबूर करना) या सर्वर प्रतिक्रिया में दिए गए डेटा का उपयोग करके मैन्युअल रूप से अपडेट किया जाना चाहिए, जिसकी प्रक्रिया पूरी तरह से मेरे उत्तर में वर्णित है। –

संबंधित मुद्दे