Backbone.ModelBinder
Backbone.ModelBinder copied to clipboard
_isSetting flag race condition when we're trying to change an input class based on input value
Hi,
I just hit an issue while defining multiple binder on the same field.
Typically, if I have following input field :
<div id="content">
<input type="text" name="foo" />
</div>
and I define following model binder :
this._modelBinder.bind(model, this.el, {
'foo': [{
selector: '[name=foo]'
}, {
selector: '[name=foo]',
elAttribute: 'class',
converter: function(model, value) {
console.log("class elAttribute triggered for foo");
return (value && value.length>3)?"error":undefined;
}
}]
});
The "class elAttribute triggered for foo" log is only displayed during model binder initialization, but never after (typically, when my foo attribute is modified)
This is due to the _isSetting lock put on target el (which is the same between both elementBinding in our case) :
- When
copyViewValuesToModel()is called, we enter the_copyViewToModel()on first elementBinding - The
_isSettinglock is put on the target el (which is the same for the other elementBindings) -
_setModel()and_copyModelToView()is called, iterating over every elementBindings. - The first one is ignored because of the
_isSettinglock, but the second one (which is targetting the same element) is ignored as well, preventingclassattribute to be calculated/updated.
I don't see how we could elegantly workaround this issue.
Anyway, if I use a DOM wrapper around my input for handling this class change, it works perfectly.
See following jsfiddle which demonstrates the issue and the workaround :
- If you enter an input value longer than 3 chars on 1st input, no error class is defined on the input, where if you do on the second input (which is wrapped into a
.field-containerelement), it works fine.
Regards,