Skip to content

Instantly share code, notes, and snippets.

@augustine-tran
Created October 26, 2013 03:07
Show Gist options
  • Save augustine-tran/7164867 to your computer and use it in GitHub Desktop.
Save augustine-tran/7164867 to your computer and use it in GitHub Desktop.
Model Associations in Sencha Touch (and ExtJS) made easy! Porting from Sencha Touch to ExtJS
Ext.define('Glandore.model.Base', {
extend: 'Ext.data.Model',
idProperty: 'id',
isNew: function() {
return this.phantom == true;
},
linkedAssociations: false,
/* uses information from the associations to fetch a parent from an associated store */
getParent: function(assocName) {
var assoc = this.associations.get(assocName);
if (!assoc) {
return null;
}
var store = this.lookupInjectStore(assoc.foreignStore);
if (!store) {
return null;
}
return store.findRecord(assoc.primaryKey, this.get(assoc.foreignKey)) || undefined;
},
getChildren: function(assocName) {
var assoc = this.associations.get(assocName),
id = this.get(assoc.primaryKey);
if (!assoc) {
return null;
}
var store = this.lookupInjectStore(assoc.foreignStore);
if (!store) {
return null;
}
store.suspendEvents(); /* make sure the store does not fire all sorts of events, triggering stuff we dont want */
store.clearFilter();
store.filterBy(function(record) {
return record.get(assoc.foreignKey) === id;
});
var range = store.getRange(); // return array of records
store.clearFilter();
store.resumeEvents();
return range;
},
/* warning, recursive down in combination with up can be dangerous when there are loops in associations */
getData: function(includeAssociated,down) {
if (includeAssociated && !this.linkedAssociations) {
this.linkedAssociations = true;
this.linkChildAssociations(includeAssociated);
this.linkAssociations(includeAssociated);
}
var data = this.callParent(arguments);
return data;
},
getFlattenedData: function(includeAssociated) {
var data = this.getData(includeAssociated, false); // don't ever recurse down when getting flattened data!
/* This function flattens the datastructure of am object such that it can be used in a form
* {foo:1,bar:{blah: {boo: 3}}} becomes {foo: 1, bar.blah.boo: 3}
* This is the only way to use associated data in a form
* thanks to http://stackoverflow.com/users/2214/matthew-crumley
*/
var count=1;
var prop;
var flatten = function(obj, includePrototype, into, prefix) {
if (count++ > 20) {console.log('TOO DEEP RECURSION'); return;} // prevent infinite recursion
into = into || {};
prefix = prefix || "";
for (var k in obj) {
if (includePrototype || obj.hasOwnProperty(k)) {
var prop = obj[k];
if (prop instanceof Array) { continue; } // Don't recurse into hasMany relations
if (prop && typeof prop === "object" &&
!(prop instanceof Date || prop instanceof RegExp)) {
flatten(prop, includePrototype, into, prefix + k + ".");
}
else {
into[prefix + k] = prop;
}
}
}
return into;
};
return flatten(data, false);
},
/* this function ONLY recurses upwards (belongsTo), otherwise the data structure could become infinite */
linkAssociations: function(includeAssociated, count) {
var associations = this.associations.items,
associationCount = associations.length,
associationName,
association,
associatedRecord,
i,
type,
foreignStore;
count = count || 0;
if (count > 10) {
console.log('Too deep recursion in linkAssociations');
return;
}
for (i = 0; i < associationCount; i++) {
association = associations[i];
associationName = association.name;
type = association.type;
foreignStore = association.foreignStore;
if (!foreignStore) {
continue;
}
if (type.toLowerCase() == 'belongsto' || type.toLowerCase() == 'hasone') {
associatedRecord = this.getParent(associationName);
if (associatedRecord) {
this[association.instanceName] = associatedRecord;
associatedRecord.linkAssociations(includeAssociated, (count+1));
}
}
}
},
linkChildAssociations: function(includeAssociated, count) {
var associations = this.associations.items,
associationCount = associations.length,
associationName,
association,
associatedRecord,
i,
type,
foreignStore;
count = count || 0;
if (count > 10) {
console.log('Too deep recursion in linkAssociations');
return;
}
for (i = 0; i < associationCount; i++) {
association = associations[i];
console.log(association);
associationName = association.name;
type = association.type;
foreignStore = association.foreignStore;
if (!foreignStore) {
continue;
}
if (type.toLowerCase() == 'hasmany') {
var children = this.getChildren(associationName);
association.setStoreName('hasMany_'+associationName+'_'+Ext.id());
var store = Ext.create('Ext.data.Store',{
model: association.associatedModel
});
store.add(children);
this[association.getStoreName()] = store;
}
}
},
lookupInjectStore: function(storeId) {
return this[storeId];
}
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment