Sometimes you need to ask a users for multiple answers to a single question. But what’s the best way to go about it?

Checkbox-field

Checkbox-field

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 ๐Ÿ™‚

Check out the demo!

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.

Enhanced by Zemanta

Learned something new? Want to become a better engineer? ๐Ÿ’Œ

Join 9,400+ people just like you already improving their skills.

Here's how it works ๐Ÿ‘‡

Leave your email and I'll send you an Interactive Modern JavaScript Cheatsheet ๐Ÿ“– right away. After that you'll get a thoughtfully written email every week aboutย React, JavaScript,ย  andย lessons learned in my 20 years of writing code for companies ranging from tiny startups to Fortune5 behemoths.



Man, I love your way of writing these newsletters. Often very relatable and funny perspectives about the mundane struggles of a dev. Lightens up my day. ~ Kostas

PS: You should also follow me on twitter ๐Ÿ‘‰ here.
It's where I go to shoot the shit about programming.