switch (method) {
case 'create': // pass-through
case 'update':
- CRM.api(model.crmEntityName, 'create', model.toJSON(), apiOptions);
+ var params = model.toJSON();
+ params.options || (params.options = {});
+ params.options.reload = 1;
+ if (!model._isDuplicate) {
+ CRM.api(model.crmEntityName, 'create', params, apiOptions);
+ } else {
+ CRM.api(model.crmEntityName, 'duplicate', params, apiOptions);
+ }
break;
case 'read':
case 'delete':
crmEntityName: crmEntityName,
toCrmCriteria: function() {
return (this.get('id')) ? {id: this.get('id')} : {};
+ },
+ duplicate: function() {
+ var newModel = new ModelClass(this.toJSON());
+ newModel._isDuplicate = true;
+ if (newModel.setModified) newModel.setModified();
+ newModel.listenTo(newModel, 'sync', function(){
+ // may get called on subsequent resaves -- don't care!
+ delete newModel._isDuplicate;
+ });
+ return newModel;
}
});
// Overrides - if specified in ModelClass, replace
// Defaults - if specified in ModelClass, preserve
_.defaults(ModelClass.prototype, {
isSaved: function() {
- var result = !this.isNew() && !this._modified;
+ var result = !this.isNew() && !this.isModified();
return result;
},
+ isModified: function() {
+ return this._modified;
+ },
_saved_onchange: function(model, options) {
if (options.parse) return;
+ // console.log('change', model.changedAttributes(), model.previousAttributes());
this.setModified();
},
setModified: function() {
* });
* CRM.Backbone.extendCollection(ContactCollection);
*
- * // Use class
+ * // Use class (with passive criteria)
* var c = new ContactCollection([], {
* crmCriteria: {contact_type: 'Organization'}
* });
* c.get(123).set('property', 'value');
* c.get(456).setDeleted(true);
* c.save();
+ *
+ * // Use class (with active criteria)
+ * var criteriaModel = new SomeModel({
+ * contact_type: 'Organization'
+ * });
+ * var c = new ContactCollection([], {
+ * crmCriteriaModel: criteriaModel
+ * });
+ * c.fetch();
+ * c.get(123).set('property', 'value');
+ * c.get(456).setDeleted(true);
+ * c.save();
* @endcode
*
+ *
* @param Class CollectionClass
* @see tests/qunit/crm-backbone
*/
return (this.crmCriteria) ? _.extend({}, this.crmCriteria) : {};
},
+ /**
+ * Get an object which represents this collection's criteria
+ * as a live model. Any changes to the model will be applied
+ * to the collection, and the collection will be refreshed.
+ *
+ * @param criteriaModelClass
+ */
+ setCriteriaModel: function(criteriaModel) {
+ var collection = this;
+ this.crmCriteria = criteriaModel.toJSON();
+ this.listenTo(criteriaModel, 'change', function() {
+ collection.crmCriteria = criteriaModel.toJSON();
+ collection.debouncedFetch();
+ });
+ },
+
+ debouncedFetch: _.debounce(function() {
+ this.fetch({reset: true});
+ }, 500),
+
/**
* Reconcile the server's collection with the client's collection.
* New/modified items from the client will be saved/updated on the
sync: CRM.Backbone.sync,
initialize: function(models, options) {
options || (options = {});
- if (options.crmCriteria) {
+ if (options.crmCriteriaModel) {
+ this.setCriteriaModel(options.crmCriteriaModel);
+ } else if (options.crmCriteria) {
this.crmCriteria = options.crmCriteria;
}
if (origInit) {