Backbone.ModelBinder icon indicating copy to clipboard operation
Backbone.ModelBinder copied to clipboard

ModelBinder incorrectly handles true/false radio button values

Open elwayman02 opened this issue 11 years ago • 11 comments

ModelBinder is unable to correctly check a radio button if its value is a boolean.

The problem manifests on line 397 of ModelBinder.js:

case 'radio':
    el.prop('checked', el.val() === convertedValue);
    break;

Let's say the element looks like this:

<input name="someRadio" type="radio" value="true" />

el.val() returns "true" as a string, but the value on the model is an actual boolean (because that's how the data is truly represented). So "true" === true evaluates to false and the radio button is not checked.

I could write a converter to force the value to be converted to a string (which I'm going to have to do in the meantime), but I think the proper solution would be to have ModelBinder check to see if convertedValue is a boolean and convert it to a string in the case of a radio button.

Something like this:

case 'radio':
    if (convertedValue === true) { convertedValue = 'true'; }
    else if (convertedValue === false) { convertedValue = 'false'; }
    el.prop('checked', el.val() === convertedValue);
    break;

elwayman02 avatar Oct 01 '13 20:10 elwayman02

@elwayman02 - this is strange. I just ran a quick test and things appear to be working fine...

Here are some snippets from my quick test - have you tried with the latest? I'm using Chrome with JQuery 1.10.2. I wonder if there is a browser difference?

     Is Animal?<br>
    <input type="radio" name="isAnimal" value="true" /> True <br/>
    <input type="radio" name="isAnimal" value="false" /> False

    this._modelBinder.bind(this.model, this.el, {isAnimal: '[name=isAnimal]'});

    this._model.on('change:isAnimal', function(){console.log('isAnimal changed to ', m.get('isAnimal'))});

    this.model.set('isAnimal', true);
    this.model.set('isAnimal', false);

theironcook avatar Oct 02 '13 14:10 theironcook

I tried it on Chrome w/ jQuery 1.10.2 and ModelBinder 1.0.5, so I'm not sure how it worked for you. I had to write the following custom converter to get it to work.

converter: function(direction, value) {
    if (_.isEqual(direction, ModelBinder.Constants.ViewToModel)) {
        return value === "true";
    } else if (value === true) {
        return "true";
    } else if (value === false) {
        return 'false';
    }
    return '';
}

elwayman02 avatar Oct 02 '13 15:10 elwayman02

I'll leave this issue open. If anyone else has the same issue I'll introduce the change to the Backbone.ModelBinder. Sorry - I just can't replicate the issue.

theironcook avatar Oct 09 '13 14:10 theironcook

I'm having this problem as well. Backbone 1.1, ModelBinder 1.0.5. My radio buttons have true and false in their value attributes. The value in my model is a boolean.

Without a converter, no radio button is selected. With this converter (Coffeescript), it works:

converter: (dir, value) -> "" + value

chris-h-sg avatar Jan 03 '14 05:01 chris-h-sg

I just experienced the same problem. I used thrar's solution to overcome it. I'm using ModelBinder 1.0.5 and Backbone 1.1.2.

cbmayer avatar Aug 16 '14 06:08 cbmayer

Checkboxes bind fine to a boolean model attribute but radio buttons do not. They seem to set the value attribute as string and are not checked when model value is set true.

dbrin avatar Jan 02 '15 23:01 dbrin

I have face the same issue, because I had given checked attribute to a radio button in group to make it checked by default. I have found that in version v1.0.5 on line 303 instead of if(el.attr('type') === 'radio' && el.attr('checked')) it should be if(el.attr('type') === 'radio' && el.is(':checked')) Since I have added checked attribute to the first radio button from the "radio button group" to make checked by default when view is rendered, the function always return the first radio button element itself.i.e. it will always return the radio button from group that has checked attribute.

technikhil314 avatar Jan 23 '15 09:01 technikhil314

I found that, if your model returns and integer value, which is used to populate the radio buttons value the ModelBinding does not select the radio button value. Providing a converter like

var radioButtonConverter = function(direction, value) {
  if (_.isEqual(direction, Backbone.ModelBinder.Constants.ViewToModel)) {                                                                                                                                                         
    return parseInt(value);
  } else {
    return value.toString();
  } 
};

seemed to work for me

akotian avatar Jun 16 '15 00:06 akotian

The way to get Boolean "value" settings to work, is to "v-bind" to the value so that Vue treats it as a JavaScript expression rather than a string.

As mentioned at the "Passing a Number" section of the guide: "

https://vuejs.org/v2/guide/components-props.html#Passing-a-Number

mgrollins avatar Feb 21 '19 23:02 mgrollins

I think you might be posting in the wrong thread @mgrollins...

elwayman02 avatar Feb 22 '19 00:02 elwayman02

Mr Trolling ? ;-)

boussou avatar Mar 14 '19 23:03 boussou