Using Backbone to improve multiselects
Blogging burns a lot of caffeine. If you enjoy my posts, you should buy me a cup of tea.
Sometimes you need to ask a users for multiple answers to a single question. But what’s the best way to go about it?
A multiselect input field is kind of strange for the user, sticks out and doesn’t really behave like everything else on the web.
A bunch of checkboxes is better for the user … but have you ever tried handling a form with dynamically created checkboxes? Let alone creating useful tests and consolidating everything into a single list of values. No decent forms framework will let you do that easily.
I had to solve this similar problem for a time and attendance software I worked on, so I made a Javascript thing to convert a select field into a checkbox-field. Then I made it into a simple jquery plugin thing for everyone to use
The idea is pretty simple:
- take a select, turn it into a list of options
- every option becomes a Checkbox model in a collection
- render each Checkbox as a CheckboxView
- connect everything with some events
What I really love about the Backbone approach is that all of this works almost magically. Instead of bending over backwards to get checkboxes and the hidden multiselect synced up, all I had to do was create some models, some views and tell them how they are connected.
This is how the field itself is created
$multiselect.find("option").each(function (i, el) { var $el = $(el); // hidden behind the scenes here is that: // 1. creating a Checkbox, correctly binds together all needed events // 2. adding it to checkboxes, takes care of rendering and adding to the DOM checkboxes.add(new Checkbox({value: $el.val(), label: $el.html(), selected: $el.attr('selected')})); });
And to make sure data is synced up between its three representations (multiselect, visual checkboxes, the data structure itself), all it takes is this:
var Checkbox = Backbone.Model.extend({ initialize: function () { this.bind("change:selected", this.toggled); this.attributes.id = this.cid; }, toggled: function () { var $opt = $multiselect.find("option[value="+this.get('value')+"]"); if (this.get('selected')) { $opt.attr("selected", "1"); }else{ $opt.removeAttr("selected"); } } });
Yep, that’s the whole model and that’s all it takes to sync everything up. Pretty cool huh? I remember trying to do this with just jQuery once … I nearly stabbed my eyes out to end the misery.
All in all the whole thing is just 123 sloc, which can only mean one thing: Backbone is cool.
If you use my checkbox-field library, it’s only going to be a single sloc for you:
$("#my_selector").checkboxField();
That’s it
Let me know what you think.
Related articles
- JQuery Multiselect – Abbreviation List (ki6i.com)
- Retrieving selected values from WPF ListBox with multiselect (stackoverflow.com)
- How can I get element state from appendchild checkbox in Javascript? (stackoverflow.com)
- Controlling Checkboxes in HTML (stackoverflow.com)
- Simulate Holding Ctrl Key (stackoverflow.com)
---
Need a freelance developer? Email me!
You should follow me on twitter
Follow @Swizec
Subscribe to RSS


