2
votes

The Ember app I'm building uses Leaflet.js for its large map. I have an observer on a model which adds a vector to the map and keeps it updated:

Qp.Region = DS.Model.extend({

  // Attributes
  name: DS.attr('string'),
  maxLat: DS.attr('number'),
  minLat: DS.attr('number'),
  minLon: DS.attr('number'),
  maxLon: DS.attr('number'),

  // Helper properties
  _vector: null,

  // Computed properties
  leafletBounds: function() {
    var properties = ['minLat', 'maxLat', 'minLon', 'maxLon'],
        bounds = [];
    for ( var i = 0; i < 2; i++ ) {
      var lat = Number(this.get(properties[i])),
          lng = Number(this.get(properties[i + 2]));
      if ( lat !== lat || lng !== lng )
        return;
      bounds.pushObject(L.latLng({
        lat: lat,
        lng: lng
      }));
    }
    return bounds;
  }.property('minLat', 'maxLat', 'minLon', 'maxLon'),

  boundsDidChange: function() {
    var existingVector = this.get('_vector'),
        vector = existingVector || Ember.Object.create({
          _layer: null,
          model: this
        }),
        bounds = this.get('leafletBounds');
    if ( !bounds )
      return;
    vector.set('bounds', bounds);
    if ( !existingVector ) {
      Qp.L.regions.pushObject(vector);
      this.set('_vector', vector);
    }
  }.observes('leafletBounds'),

  shouldRemoveSelf: function() {
    if ( !this.get('isDeleted') && !this.get('isDestroying') )
      return;
    var existingVector = this.get('_vector');
    if ( existingVector ) {
      Qp.L.regions.removeObject(existingVector);
      this.set('_vector', null);
    }
  }.observes('isDeleted', 'isDestroying')

})

N.B. This worked perfectly with Ember Data rev. 0.13.

Now I'm updating to Ember Data 1.0 beta 2, and the vectors are no longer added to the map. If I save a reference to the model on init...

init: function() {
  this._super.apply(this, arguments);
  window.test = this;
}

...and call window.test.boundsDidChange() from the Chrome dev tools console, the vector for the last region in my fixtures appears. Therefore, I know everything is still working, except the observer is no longer being called when the model data loads.

How can I get the boundsDidChange observer to trigger when the model loads or updates?

1

1 Answers

1
votes

This is probably due to a change in rc8. Look for the section titled "UNCONSUMED COMPUTED PROPERTIES DO NOT TRIGGER OBSERVERS" : http://emberjs.com/blog/2013/08/29/ember-1-0-rc8.html

The change is that computed properties are not ever computed until they are actually retrieved by something, which means that observers on them don't work reliably if they are not being displayed directly.

You could either get the leafletBounds property in your object init, or you could have your boundsDidChange function observe all of the components of the computed property.

boundsDidChange: function() { // nothing in the method body changes
}.observes('minLat', 'maxLat', 'minLon', 'maxLon')