Computed property trigger not working with child property

edited November 2016 in Enyo 2.7
Hi , I'm trying to simply trigger a recompute when the child property on a property of my Component changes.
var MainView = kind({
	...

	computed: [
		{ method: 'compute', path: [ 'trigger', 'trigger.count' ] }
	],

	compute: function() {
		console.log('computing...');
		var that = this;
		setTimeout(function() {
			that.set('trigger.count', that.trigger.count + 1);
		}, 1000);
	},

	create: function() {
		this.inherited(arguments);
		this.set('trigger', { count: 1 });
	}
}
Now when I initially set 'trigger', the function runs. When I increment it within the trigger, the function doesn't ever run again. So it seems it doesn't work when I'm trying to observe a child property change.

Any help would be appreciated. I'm sure I'm doing something stupid.

Comments

  • tl;dr - The problem here is that computed properties aren't settable. I'm not sure what your use case is but if you want to update a property over an interval, I'd suggest using setInterval schedule it and then set the property as you've done here. You can then observe that property to affect other changes.

    PS - Don't forget to clear the interval in your kind's destroy method!


    Little more background ...
    You're getting a sort of false positive in your example because you're setting a path (trigger) that a computed property uses and since that property hasn't been computed yet, it is initially to populate the cache. Setting trigger.count doesn't cause the update because trigger isn't an observable object (like an Enyo Control) -- it's just a regular object -- so the notification chain can't start.
  • What do you mean that computed properties are not "settable"?

    Anyways, the example I posted was just to test whether I could trigger the computed function multiple times (the first time by setting 'trigger' and multiple times thereafter by updating a property on 'trigger'. But what you said makes sense about it not being observable as it's just a plain JS object.

    My real use case is that I'm making multiple calls to a Web API and I want to update the spinner.showing property based on all of those calls. Therefore my path needs to be able to handle ['col1.status', 'col2.status', ...] which wasn't working.
    ...
    computed: [
        { method: 'isLoading', path: ['hotels.status', 'tvlist.status'] }
    ],
    
    bindings: [
        { from: 'isLoading', to: '$.installPanel.$.spinner.showing' }
    ],
    
    isLoading: function() {
        return
            (this.hotels && this.hotels.isBusy()) ||
            (this.tvlist && this.tvlist.isBusy());
    },
    
    create: function() {
        this.inherited(arguments);
        this.set('hotels', new HotelCollection());
        this.set('tvlist', new TvCodeCollection());
        this.set('ratio', new Collection([
            '4by3', '16by9'
        ]));
    
        this.hotels.fetch();
        this.tvlist.fetch();
    }
    ...
    Should this work or not?
  • By 'settable', I mean that you cannot explicitly set the value of a computed property via this.set('computedProperty', newValue); it can only be retrieved via this.get('computedProperty') which will either invoke this.computedProperty() or retrieve the value from cache if the dependent paths haven't changed.

    What you have looks like it should work. status should be observable on a Collection. What have you already tried to troubleshoot this?
Sign In or Register to comment.