Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I observe *all* property changes on a model object?

Tags:

ember.js

I have a model built from a JSON object.

// extend the json model to get all props
App.Model = Ember.Object.extend(window.jsonModel);

I want to automatically save the model when anything is updated. Is there any way I can add an observer to the whole model?

EDIT: // adding the solution I currently go

For now I do:

// XXX Can't be right
for (var prop in window.jsonModel) {
    if (window.jsonModel.hasOwnProperty(prop)) {
        App.model.addObserver(prop, scheduleSave);
    }
}

This is a large form, which means I'm adding tons of observers – it seems so inefficient.

A firebug breakpoint at Ember.sendEvent() reveals that there are events called App.model.lastName:change being sent. I could hack in an intercept there, but was hoping for an official way.

like image 294
Martin Algesten Avatar asked Feb 08 '12 12:02

Martin Algesten


3 Answers

You can bind to isDirty property of subclass of DS.Model. The isDirty changes from false to true when one of model properties changes. It will not serve well for all cases because it changes only once until reset or committed, but for your case -

I want to automatically save the model when anything is updated. Is there any way I can add an observer to the whole model?

it may work fine.

like image 88
Shimon Rachlenko Avatar answered Oct 18 '22 19:10

Shimon Rachlenko


From the article:

autosave: function(){
    this.save();
}.observes('attributes'),


save: function(){
  var self = this,
    url = this.get('isNew') ? '/todos.json' : '/todos/'+this.get('id')+'.json',
    method = this.get('isNew') ? 'POST' : 'PUT';

  $.ajax(url, {
    type: 'POST',
    // _method is used by Rails to spoof HTTP methods not supported by all browsers
    data: { todo: this.get('attributes'), _method: method },
    // Sometimes Rails returns an empty string that blows up as JSON
    dataType: 'text',
    success: function(data, response) {
      data = $.trim(data);
      if (data) { data = JSON.parse(data); }
      if (self.get('isNew')) { self.set('id', data['todo']['id']); }
    }
  });
},

isNew: function(){
   return !this.get('id');
}.property('id').cacheable(),
like image 45
MattK Avatar answered Oct 18 '22 20:10

MattK


I had the same requirement, and not finding a suitable answer, I implemented one.

Try this: https://gist.github.com/4279559

Essentially, the object you want to observe all the properties of MUST be a mixed of Ember.Stalkable. You can observe the properties of that object as 'item.@properties' (or, if you bake observers directly on the Stalkable, '@properties' alone works. "@ownProperties", "@initProperties" and "@prototypeProperties" also work, and refer to (properties that are unique to an instance and not defined on any prototype), (properties that are defined as part of the create() invocation), and (properties that are defined as part of the class definition).

In your observers, if you want to know what properties changed and invoked the handler, the property "modifiedProperties", an array, will be available with the names of the changed properties.

like image 24
Fordi Avatar answered Oct 18 '22 20:10

Fordi