jeudi 23 avril 2015

How to pass multiple (dynamic) Parameter to store.find() method // avoid duplicate entrys

we have a search formular with multiple (dynamic generated) input fields. Our server rest api is Spring MVC powered and accepts a call like this:

/rest/search/1?identnummer=0000000&parameter2=xy&parameter3=zy

In the search method of the formular (action: search)

i collect all parameters and build up a string like this:

queryparams =  1?identnummer=0000000&parameter2=xy&parameter3=zy

and then call the store.find method:

that.store.find('trefferliste', queryparams).then(function(response) {
            console.log("Success loading hit list...", response);
        }, 
        function(error) {
            console.error(error);
                that.transitionTo('trefferliste');
             }
        });

I overwrote the buildURL Method (removed encodeURIComponent()

if (id && !Ember.isArray(id)) { url.push(encodeURIComponent(id)); }

for the TrefferlisteAdapter

App.TrefferlisteAdapter = App.ApplicationAdapter.extend({
buildURL: function(type, id) {

    var url = [];
    var host = helicDevServer;
    var prefix = this.urlPrefix();

    if (type) { url.push(this.pathForType(type)); }
    if (id && !Ember.isArray(id)) { url.push(id); }
    if (prefix) { url.unshift(prefix); }

    url = url.join('/');
    if (!host && url) { url = '/' + url; }
    return url;
}
});

After the request is send and i receive the expected json response, i have two entrys in the store:

Entry 1 :  id = 1
Entry 2 :  id = 1?identnummer=0000000&parameter2=xy&parameter3=zy

The first entry is the expected one, the second is corrupt and causes this error:

Error: Assertion Failed: Expected an object as `data` in a call to `push` for App.Trefferliste , but was undefined
at new Error (native)
at Error.EmberError (/js/libs/ember-stable/ember.debug.js:12061:21)
at Object.Ember.default.assert (/js/libs/ember-stable/ember.debug.js:5162:13)
at ember$data$lib$system$store$$Service.extend.push (/js/libs/ember-canary/ember-data.js:10849:15)
at /js/libs/ember-canary/ember-data.js:4805:24
at Object.Backburner.run (/js/libs/ember-stable/ember.debug.js:217:27)
at ember$data$lib$system$store$$Service.extend._adapterRun (/js/libs/ember-canary/ember-data.js:11143:33)
at /js/libs/ember-canary/ember-data.js:4802:22
at tryCatch (/js/libs/ember-stable/ember.debug.js:46977:16)
at invokeCallback (/js/libs/ember-stable/ember.debug.js:46989:17)

So my questions are:

  • Is this a acceptable method to pass the dynamic parameters to the find method?
  • Does someone know how i can prevent the corrupt item to get in the store?

Some more information about my setup:

DEBUG: Ember      : 1.11.3
ember.debug.js:5197 DEBUG: Ember Data : 1.0.0-beta.17+canary.4ad70aab2a
ember.debug.js:5197 DEBUG: jQuery     : 2.1.3

Serializer Method for Sideloading my records:

/**
Deserialize nested JSON payload into a flat object with sideloaded relationships. */
App.NestedSerializer = DS.RESTSerializer.extend({

/**
Generate a unique ID for a record hash
@param {DS.Store} store
@param {DS.Model} type
@param {Object} hash The record hash object
@return {String} The new ID
*/
generateID: function(store, type, hash){
var id, primaryKey,
serializer = store.serializerFor(type);

type._generatedIds = type._generatedIds || 0;

// Get the ID property name
primaryKey = Ember.get(serializer, 'primaryKey') || 'id';
id = hash[primaryKey];

// Generate ID
if (!id) {
  id = ++type._generatedIds;
  hash[primaryKey] = id;
}
return id;
},


/**
Sideload a record hash to the payload

@method sideloadRecord
@param {DS.Store} store
@param {DS.Model} type
@param {Object} payload The entire payload
@param {Object} hash    The record hash object
@return {Object} The ID of the record(s) sideloaded
*/
sideloadRecord: function(store, type, payload, hash) {
var id, sideLoadkey, sideloadArr, serializer;

// If hash is an array, sideload each item in the array
if (hash instanceof Array) {
  id = [];
  hash.forEach(function(item, i){
    id[i] = this.sideloadRecord(store, type, payload, item);  
  }, this);
}
// Sideload record
else if (typeof hash === 'object') {
  sideLoadkey = type.typeKey.pluralize();   // Sideloaded keys are plural
  sideloadArr = payload[sideLoadkey] || []; // Get/create sideload array
  id = this.generateID(store, type, hash);

  // Sideload, if it's not already sideloaded
  if (sideloadArr.findBy('id', id) === undefined){      
    sideloadArr.push(hash);
    payload[sideLoadkey] = sideloadArr;
  }
}
// Assume it's already pointing to a sideloaded ID
else {
  id = hash;
}

return id;
},

/**
Process nested relationships on a single hash record

@method extractRelationships
@param {DS.Store} store
@param {DS.Model} type
@param {Object} payload The entire payload
@param {Object} hash    The hash for the record being processed
@return {Object} The updated hash object
*/
processRelationships: function(store, type, payload, hash) {
// If hash is an array, process each item in the array
if (hash instanceof Array) {
  hash.forEach(function(item, i){
    hash[i] = this.processRelationships(store, type, payload, item);  
  }, this);
}

else {

  // Find all relationships in this model
 type.eachRelationship(function(key, relationship) {
    var related = hash[key],         // The hash for this relationship
        relType = relationship.type; // The model type

    this.generateID(store, type, hash);
    hash[key] = this.sideloadRecord(store, relType, payload, related);
    this.processRelationships(store, relType, payload, related); 

  }, this);
}

return hash;
},

/**
(overloaded method)
Starts the deserialized of all payloads.

@method normalizePayload
@param {Object} payload
@return {Object} the normalized payload
 */
extract: function(store, type, payload, id, requestType) {

payload = this.normalizePayload(payload);
var rootKeys = Ember.keys(payload);

// Loop through root properties and process extract their relationships
rootKeys.forEach(function(key){
  var type = store.container.lookupFactory('model:' + key.singularize()),
      hash = payload[key];

// If the key resolves to a model type, sideload any embedded relationships
  if (type) {
     this.processRelationships(store, type, payload, hash);
  }
}, this);

console.log(payload);

return this._super(store, type, payload, id, requestType);
}
,
normalizePayload: function(payload) {

if(payload.elementBeanWrapper){
  payload.dashboard = payload.elementBeanWrapper;
  delete payload.elementBeanWrapper;  
    }
 return payload;
 }
});

App.ApplicationSerializer = App.NestedSerializer;




Aucun commentaire:

Enregistrer un commentaire