Bindings not always firing when model changes

edited February 2015 in Enyo 2.5
Here's my situation:

I have a kind that has a number of onyx.Inputs which are bound to various attributes of an enyo.Model. When the model is changed, the inputs are populated with data from the model. Pretty standard stuff.

ie:
bindings: [
	{from: ".activeModel.attribute1", to: ".$.attribute1Input.value"},
]
The problem that I am having is that when I change the model, the bindings only fire for the attributes that have changed. This is not normally a problem, except when there are changes to the inputs that have not been saved back to the model.

ie. model1.attribute1 = 42, model2.attribute1 = 42. I assign model1 as activeModel and .$.attribute1Input.value is set to 42. I change attribute1Input.value to 43 and do not save changes back to the model, then switch activeModel to model2, attribute1Input still displays as 43 because the binding has not fired because the underlying models are still the same.

If I try to fire the bindings manually using a activeModelChanged function and a chunk of code like this:
activeModelChanged: function(){
	for (i = 0; i < this.bindings.length; i++)
	{
		this.bindings[i].sync(true);
	}
},
The app can get stuck in an infinite loop.

Is there any way to force the bindings to fire whenever the model has changed, even if the attributes have not, or should I be re-thinking how I'm handling my bindings?

Comments

  • Hi @Aressel, how are you changing the active model property? If you're using a setter, you can do something like
    this.set('activeModel', model1, {force: true});
    This will force any change handlers to run, regardless of whether or not there was a detected change in the property you're setting.
  • edited February 2015
    Hi @arrontam, thanks for the suggestion!

    To answer your question, this property gets set from an owner object, so I was using

    this.$.panel.set('activeModel', model1);

    and tried your suggestion, so it wound up looking like

    this.$.panel.set('activeModel', model1, {force: true});

    Unfortunately, no luck. It looks like the bindings are still only firing on the attributes that have changed. Would it make a difference to set it from within the kind itself?
  • edited March 2015
    I think what happens is the following. Your component initializes, creates bindings to the model instance assigned to the 'activeModel' property: model1. The initialized binding is now linked to the model1 instance.

    When you assign a different model instance - model2 - to the 'activeModel' property, your bindings are probably not being refreshed, and so they are still watching the model1 instance.

    I think one way to work around this, would be to use a modelController as your activeModel to act as a proxy between your component and the model1 or model2 instances. If you bind to the modelController, it will forward changes on it's underlying model, but the binding itself will be linked to the modelController rather instead of to the model instance.

    To switch between model1, and model2, you simply need to assign the models to the modelController's model property. You might need to sync the modelController after changing it's model, I'm not sure about that part.
  • @ruben_vreeken Thanks for the tip. I tried it out, and it is still only refreshing the bindings for the model properties that have actually changed.

    I wound up going with a simpler, if more hackish solution. I set the activeModel property to null before setting it to model2, and that forces a refresh of everything.

    I'm starting to suspect that there is an underlying problem with refreshing bindings in Enyo 2.5.
  • edited March 2015
    I know in the case of a modelController it is sometimes needed to force a sync, but at least it lets you swap out the model instance.

    You might be right about there possibly being an underlying problem though. I ran into a binding that did not update as well this week (see: http://forums.enyojs.com/discussion/2333/have-bindings-changed). I noticed the 2.5.1 pre-releases mentioned some bug-fixes related to improperly updating bindings so there has definitely been some changes around the binding implementation. Hopefully someone from the enyo team can check it out?
Sign In or Register to comment.