最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Ember computed property not being updated - Stack Overflow

programmeradmin5浏览0评论

I'm not too entirely sure why my puted property isn't returning updated values.

I have a list of options that a user can click through, and the action updates a property, which is an Ember Object, for the controller. I have a puted property that loops through the object, looks for keys that have non-null values for that Ember Object property, and if it does find one, returns false, otherwise true.

Here's the stuff:

App.SimpleSearch = Ember.Object.extend({
    init: function() {
        this._super();

        this.selectedOptions = Ember.Object.create({
            "Application" : null,
            "Installation" : null,
            "Certification" : null,
            "Recessed Mount" : null,
            "Width" : null,
            "Height" : null,
            "Heating" : null,
            "Power" : null
        });
    },

    selectedOptions: {},

    numOfOptions: 0,

    allOptionsSelected: function() {
        var selectedOptions = this.get('selectedOptions');
        for (var option in selectedOptions) {
            console.log(selectedOptions.hasOwnProperty(option));
            console.log(selectedOptions[option] === null);
            if (selectedOptions.hasOwnProperty(option)
                && selectedOptions[option] === null) return false;
        }
        return true;
    }.property('selectedOptions')
});


App.SimpleSearchRoute = Ember.Route.extend({
    model: function() {
        return App.SimpleSearch.create({
            'SimpleSearchOptions': App.SimpleSearchOptions,
            'numOfOptions': App.SimpleSearchOptions.length
        });
    },
    setupController: function(controller, model) {
        controller.set('model', model);
    }
});


App.SimpleSearchController = Ember.ObjectController.extend({
    getProductsResult: function() {
        var productsFromQuery;
        return productsFromQuery;
    },

    setSelection: function (option, selectionValue) {
        this.get('selectedOptions').set(option, selectionValue);
        this.notifyPropertyChange('allOptionsSelected');
    },

    actions: {
        registerSelection: function(option) {
            console.log('registering selection');
            console.log(this.get('allOptionsSelected'));
            console.log(this.get('selectedOptions'));
            this.setSelection(option.qname, option.value);
        },

The action in the controller, registerSelection is firing just fine, but I only see the console.log from the SimpleSearch model once. Once the property is puted that first time, it isn't paid attention to after that, which means that the puted property isn't observing the changes to selectedOptions whenever this is called:

setSelection: function (option, selectionValue) {
    this.get('selectedOptions').set(option, selectionValue);
    this.notifyPropertyChange('allOptionsSelected');
},

Edit:

I actually solved my issue without changing anything.

I've changed the following line:

this.notifyPropertyChange('allOptionsSelected');

to:

this.get('model').notifyPropertyChange('selectedOptions');

notifyPropertyChange needs to be called within the context of the model (or the Ember Object that has observers of a specific property), and the string sent as an argument is the name of the property that was updated.

After I made that change, it worked as intended.

I'm not too entirely sure why my puted property isn't returning updated values.

I have a list of options that a user can click through, and the action updates a property, which is an Ember Object, for the controller. I have a puted property that loops through the object, looks for keys that have non-null values for that Ember Object property, and if it does find one, returns false, otherwise true.

Here's the stuff:

App.SimpleSearch = Ember.Object.extend({
    init: function() {
        this._super();

        this.selectedOptions = Ember.Object.create({
            "Application" : null,
            "Installation" : null,
            "Certification" : null,
            "Recessed Mount" : null,
            "Width" : null,
            "Height" : null,
            "Heating" : null,
            "Power" : null
        });
    },

    selectedOptions: {},

    numOfOptions: 0,

    allOptionsSelected: function() {
        var selectedOptions = this.get('selectedOptions');
        for (var option in selectedOptions) {
            console.log(selectedOptions.hasOwnProperty(option));
            console.log(selectedOptions[option] === null);
            if (selectedOptions.hasOwnProperty(option)
                && selectedOptions[option] === null) return false;
        }
        return true;
    }.property('selectedOptions')
});


App.SimpleSearchRoute = Ember.Route.extend({
    model: function() {
        return App.SimpleSearch.create({
            'SimpleSearchOptions': App.SimpleSearchOptions,
            'numOfOptions': App.SimpleSearchOptions.length
        });
    },
    setupController: function(controller, model) {
        controller.set('model', model);
    }
});


App.SimpleSearchController = Ember.ObjectController.extend({
    getProductsResult: function() {
        var productsFromQuery;
        return productsFromQuery;
    },

    setSelection: function (option, selectionValue) {
        this.get('selectedOptions').set(option, selectionValue);
        this.notifyPropertyChange('allOptionsSelected');
    },

    actions: {
        registerSelection: function(option) {
            console.log('registering selection');
            console.log(this.get('allOptionsSelected'));
            console.log(this.get('selectedOptions'));
            this.setSelection(option.qname, option.value);
        },

The action in the controller, registerSelection is firing just fine, but I only see the console.log from the SimpleSearch model once. Once the property is puted that first time, it isn't paid attention to after that, which means that the puted property isn't observing the changes to selectedOptions whenever this is called:

setSelection: function (option, selectionValue) {
    this.get('selectedOptions').set(option, selectionValue);
    this.notifyPropertyChange('allOptionsSelected');
},

Edit:

I actually solved my issue without changing anything.

I've changed the following line:

this.notifyPropertyChange('allOptionsSelected');

to:

this.get('model').notifyPropertyChange('selectedOptions');

notifyPropertyChange needs to be called within the context of the model (or the Ember Object that has observers of a specific property), and the string sent as an argument is the name of the property that was updated.

After I made that change, it worked as intended.

Share Improve this question edited Feb 11, 2014 at 22:57 Nathan Lutterman asked Feb 4, 2014 at 20:18 Nathan LuttermanNathan Lutterman 1,8854 gold badges24 silver badges38 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 11

Ember doesn't observe objects for any change on the object, it observes a single property.

How is this affecting you? Well in this method you are watching selectedOptions, but that object itself is still the same object, you might be changing properties on it, but not the object itself. And then you are telling Ember in the scope of the controller that allOptionsSelected has changed, so it regrabs it, but it doesn't recalculate it because it's not dirty, it just changed. You'd really want to say selectedOptions has changed to get allOptionsSelected to recalculate its value. Unfortunately you're doing this in the scope of the controller, so telling the controller that property has changed doesn't matter to it.

allOptionsSelected: function() {
  var selectedOptions = this.get('selectedOptions');
  for (var option in selectedOptions) {
     console.log(selectedOptions.hasOwnProperty(option));
     console.log(selectedOptions[option] === null);
     if (selectedOptions.hasOwnProperty(option)
        && selectedOptions[option] === null) return false;
     }
  return true;
}.property('selectedOptions')

Here's a dummy example showing what things cause it to actually update.

http://emberjs.jsbin./iCoRUqoB/1/edit

Honestly since you're not watching particular properties I'd probably do an array, or create a method on the object that handles adding/removing/modifying the properties so you could fire from within it's scope a property change updating all parent listeners with the changes.

Ember puted property dependent keys can be a

  1. property key. in example: 'jobTitle'
  2. puted property key. in example: 'panyName'
  3. property key of an object. in example: 'salesAccount.name and salesAccount.website'

Example extracted from Ember.model definition:

...
   jobTitle : DS.attr('string'),
   salesAccount: belongsTo('salesAccount'),

   panyName: Ember.puted('jobTitle', 'salesAccount.name', {
    get: function () {
      return this.get('salesAccount.name');
    }
  }),

  panyWebsite: Ember.puted('salesAccount.website', 'panyName',  {
    get: function () {
      return this.get('salesAccount.website');
    }
  })
...
发布评论

评论列表(0)

  1. 暂无评论