Skip to content

Instantly share code, notes, and snippets.

@yuristrelets
Last active August 29, 2015 14:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save yuristrelets/9b543be8cd8af27d0cd9 to your computer and use it in GitHub Desktop.
Save yuristrelets/9b543be8cd8af27d0cd9 to your computer and use it in GitHub Desktop.
ExtJS advanced model that is able to update hasMany associations.
/**
* Improved {@link Ext.data.Model}.
* Can automatically update foreign keys and default filter value for hasMany associations.
*/
Ext.define('App.model.AssocModel', {
extend: 'Ext.data.Model',
/**
* @private
* Copies data from the passed record into this record. If the passed record is undefined, does nothing.
*
* If this is a phantom record (represented only in the client, with no corresponding database entry), and
* the source record is not a phantom, then this record acquires the id of the source record.
*
* ADDED: If this is a phantom record and has hasMany associations, then foreign keys, filter value and `modelDefault` store property
* for this associations will be updated.
*
* @param {Ext.data.Model} sourceRecord The record to copy data from.
* @return {String[]} The names of the fields which changed value.
*/
copyFrom: function(sourceRecord) {
var me = this,
fields = me.fields.items,
fieldCount = fields.length,
modifiedFieldNames = [],
field, i = 0,
myData,
sourceData,
idProperty = me.idProperty,
name,
value;
if(sourceRecord) {
myData = me[me.persistenceProperty];
sourceData = sourceRecord[sourceRecord.persistenceProperty];
for (; i < fieldCount; i++) {
field = fields[i];
name = field.name;
// Do not use setters.
// Copy returned values in directly from the data object.
// Converters have already been called because new Records
// have been created to copy from.
// This is a direct record-to-record value copy operation.
// don't copy the id, we'll do it at the end
if (name != idProperty) {
value = sourceData[name];
// If source property is specified, and value is different
// copy field value in and build updatedFields
if (value !== undefined && !me.isEqual(myData[name], value)) {
myData[name] = value;
modifiedFieldNames.push(name);
}
}
}
// If this is a phantom record being updated from a concrete record, copy the ID in.
if (me.phantom && !sourceRecord.phantom) {
// beginEdit to prevent events firing
// commit at the end to prevent dirty being set
me.beginEdit();
me.setId(sourceRecord.getId());
// update nasMany associations
me.updateHasManyAssociations(sourceRecord.getId());
me.endEdit(true);
me.commit(true);
}
}
return modifiedFieldNames;
},
/**
* @private
* Update foreign key value for hasMany associations.
* @param {int} newId
*/
updateHasManyAssociations: function(newId) {
var me = this,
associations = me.associations.items,
associationCount = associations.length,
association, associatedStore,
type, name, foreignKey, filterProperty,
filters, filter;
for(var i = 0; i < associationCount; i++) {
association = associations[i];
type = association.type;
name = association.name;
foreignKey = association.foreignKey;
filterProperty = association.filterProperty || foreignKey;
switch(type) {
case 'hasMany':
associatedStore = me[association.storeName];
if(associatedStore) {
// update store associated foreign key fields
// for items are already added to store
//
if(associatedStore.getCount() > 0) {
associatedStore.each(function(item) {
item.set(foreignKey, newId);
});
}
// update store `modelDefaults` foreign key property
// for future items
//
associatedStore.modelDefaults[filterProperty] = newId;
// update store filter value
// for saving/loading store operations
//
filters = associatedStore.filters;
filter = filters.getAt(filters.findIndex('property', filterProperty));
if(filter) {
filter.setValue(newId);
}
}
break;
}
}
}
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment