Ember.js Controller with computed property not being recomputed

777 views Asked by At

I'm trying to add permissions to groups, and I have a drag and drop set up so that a user can pull the unselected permissions over to selected, or vice versa. Unselected permissions are computed via removing the selected permissions from all permissions. This code is all functioning properly. The first time a user brings up the page, only those permissions that are unselected appear in the unselected side, and the same for selected.

However, when the user chooses another group to look at, the selected side is correct, while the unselected side shows what was displayed for the last group. Here is the route and controller:

App.GroupsEditRoute = Ember.Route.extend({
  setupController: function(controller, model) {
    this._super(controller, model);
    controller.set('allPermissions', this.store.find('permission'));
  },
  actions: {
    'update': function(group){
      var route = this;
      group.save().then(function(){
        route.transitionTo('groups');
      });
    },
    'cancel': function(group){
      group.rollback();
      this.transitionTo('groups');
    },
    'delete': function(group){
      group.destroyRecord();
      this.transitionTo('groups');
    }
  }
});

App.GroupsEditController = Ember.ObjectController.extend({
  unselectedPermissions: function() {
    console.log('UNSELECTED');
    var allPermissions=this.get('allPermissions');
    var permissions=this.get('permissions');
    var self=this;

    allPermissions.then( function() {
      permissions.then( function() {
        var unselected=allPermissions.filter(function(permission) {
          return !permissions.contains(permission);
        });
        unselected=Ember.ArrayProxy.createWithMixins(Ember.SortableMixin, {
          sortProperties: ['name'],
          content: unselected
        });
        self.set('unselectedPermissions',unselected);
      });
    });
  }.property('model.unselectedPermissions'),
  selectedPermissions: function() {
    console.log('SELECTED');
    return Ember.ArrayProxy.createWithMixins(Ember.SortableMixin, {
      sortProperties: ['name'],
      content: this.get('permissions')
    });
  }.property('model.selectedPermissions')
});

When I use unselectedPermissions in my view via {{#each}}, it only fires once. I never see UNSELECTED in my log after that. However, the SELECTED, which is used in the same fashion, fires every time. Of course, the data displayed on the page is not updated, either, unless I refresh.

The setupController is being called each time a page is displayed, as it should.

I'm not sure what I'm doing wrong.

Any ideas?

1

There are 1 answers

1
Kingpin2k On BEST ANSWER

in general computed properties shouldn't be set. When you set them you destroy the computed property portion of the code. There are a couple of different ways to handle this, the easiest is using an observer instead of computed property and setting the property.

unselectedPermissionList: [],
unselectedWatcher: function() {
    console.log('UNSELECTED');
    var allPermissions=this.get('allPermissions');
    var permissions=this.get('permissions');
    var self=this;

    allPermissions.then( function() {
      permissions.then( function() {
        var unselected=allPermissions.filter(function(permission) {
          return !permissions.contains(permission);
        });
        unselected=Ember.ArrayProxy.createWithMixins(Ember.SortableMixin, {
          sortProperties: ['name'],
          content: unselected
        });
        self.set('unselectedPermissionList',unselected);
      });
    });
  }.observes('selectedPermissions')

The other way is to return an array reference, then push objects into that array after the fact.

unselectedWatcher: function() {
    console.log('UNSELECTED');
    var allPermissions=this.get('allPermissions'),
        permissions=this.get('permissions'),
        self=this,
        ret = [];

    allPermissions.then( function() {
      permissions.then( function() {
        var unselected=allPermissions.filter(function(permission) {
          return !permissions.contains(permission);
        });
        unselected=Ember.ArrayProxy.createWithMixins(Ember.SortableMixin, {
          sortProperties: ['name'],
          content: unselected
        });
        unselected.forEach(function(item){
          ret.pushObject(item);
        });
      });
    });

    return ret;
  }.property('selectedPermissions')

Additionally your two properties claim to be dependent on each other, which should fire an infinite loop of property updating (a changes, b is dirty, b updates, a is dirty etc).

I'm not sure why selectedPermissions is a computed property, it seems like it would just be a list that's added to or removed from, and unselectedPermissions would just be allPermisions not selectedPermissions