Backbone.ModelBinder
Backbone.ModelBinder copied to clipboard
Bind To A Group Of Checkboxes For Same Attribute
Is it possible to bind to a group of checkboxes that pertain to the same attribute?
When I define my checkbox names as name=options[]
in html, the backbone model options[]
field gets set to true
if one of the checkboxes is set instead of options
being set to an array of the checked checkboxes values.
I tried to repeat this issue in Example 3, maybe using will help you.
Your example does not perform as I would expect it to. When I check one of the options
checkboxes, all the checkboxes are automatically selected.
same issue :)
If your binding checkbox's without specifying bindings, the checkboxes need to have unique names - otherwise each of the checkbox elements will be bound to the same model's attribute name. That's why when you check one checkbox the other 2 are updated with the same value - they are all bound to the same model attribute.
So, in your fiddle example you'd need to define your checkboxes with something like this...
<input type="checkbox" name="jam" value="Jam"/>Jam <br/>\
<input type="checkbox" name="nutella" value="Nutella"/>Nutella<br/>\
<input type="checkbox" name="rum" value="Rum"/>Rum<br/>
Doesn't your model uniquely specify the options by a unique name?
Misunderstanding here. That's the point of the issue, that multiple choice input is represented as combination of checkboxes. Truly, it's seems like feture request.
Please show me how your unique checkbox values are stored in your model - the data structure. For example...
var model = new Backbone.Model();
model.set( {jam: false, nutella: true, rum: false} );
model.set( {choices: {jam: false, nutella: true, rum: false}} );
Really I don't have issues about that, but I think it should looks like that. In fiddle, meal1
and meal2
attibutes of moedl supposed to be same.
So maybe if ModelBinder run into html with checkboxes with same names, it should treat them as options of multiple select.
@summerisgone "So maybe if ModelBinder run into html with checkboxes with same names, it should treat them as options of multiple select."
OK, I might be able to enhance the model binder so that if there are multiple checkboxes with the same name - it could use the DOM elements value as the model attributes name - similar to how radio buttons work. Which ends up setting the model's corresponding attribute with the same name - does that make sense?
@theironcook The structure of my model is as follows
var model = new Backbone.Model();
selected_options = [1,2,5] // Values from selected checkboxes
model.set({option: selected_options });
@joeytheman Sorry but the model binder won't support arrays of properties like that - one reason is that there is no 'change' event that backbone will trigger when you push individual values to your array - you have to reset the entire thing each time to trigger a change event. - w/out the change event, view's won't know anything has changed.
If you can manage your options like this... Then you can use the model binder for checkboxes if I extend it a little bit like I described to @summerisgone. You could then convert the options internally to an array like you describe but you can't bind to the array - it would be a read-only calculated array.
model.set( {jam: false, nutella: true, rum: false} );
@theironcook Couldn't a change event just be triggered manually when the array is altered?
I am unable to manage my options in the way that @summerisgone described.
Can model binder be extended to check if the last two characters of the name are []
then react accordingly?
@joeytheman
The model binder listens for the backbone model 'change' event and then queries the backbone changedAttributes() function - this is the most generic but also efficient implementation for the model binder - it produces the minimal amount of updates from the model to the view. Which means, trigger a change event without actually changing the entire array won't do anything. So, if you just internally call array.push() and then trigger a 'change' event on the model nothing happens. The alternative is to create a brand new array and overwrite the old one every single time - not ideal but that would work.
Updating the model binder to handle array objects is beyond the scope of the model binder - that type of functionality belongs in the backbone model get() function - the get() function would need to accept an attribute name that contained '[xxx]' at the end of the attribute name and resolve that to the attributes array index.
Another possibility would be to create an intermediate model in your view that your binding too - similar to the MVVM pattern that abstracted out setting named options in your model as an array... The optionsModel below becomes a model where the names are indexes of the options - the element names you'll bind too will have names that are option indexes. Then you will have to push the optionsModel back into your real model
// in view
initialize: function(){
this._optionsModel = new Backbone.Model();
_,range(10).each(function(optionIndex){
// if view's model has option set
var data = {};
data[i] = true;
this._optionsModel.set(data);
}, this);
}
+1
This issue is a major problem for me.
I have an array of strings in my model (something like newsletters: ["weekly", "daily"]
) which should be represented (and changed) by multiple checkboxes in the html, in which the user can choose which newsletters does he wish to accept.
Scenario:
- User starts with an empty array in his model - []. The html has 3 checkboxes, all unchecked: "daily", "weekly", "monthly".
- The user checks the "daily" checkbox - the word "daily" is added to the "newsletter" attribute in his model: ["daily"].
- The user checks the "weekly" checkbox - the word "weekly" is added to the "newsletter" attribute in his model: ["daily", "weekly"]
I have tried playing with the collectionbinder as well and couldn't get the desired result.
Not a perfect solution, but working: http://jsfiddle.net/mingliangfeng/j4Hx5/23/
any other solution out there right now?