Creating Dynamic checkboxes with knockout.js

Today we are going to discuss a little about Knockout.js. Specifically when you are trying to create a page that loads checkboxes being dynamically created by some data source. The data source is not important in this case.

What is Knockout.js

For those of you that do not know what Knockout is, I will be doing another post series soon on what knockout is and how it relates to MVVM (Model View ViewModel). I will however, give a brief explanation for reference to those just starting to understand the MVVM pattern.

MVVM or Model View ViewModel is a design pattern used to separate your view from the any business logic and data access layers. This is done through some sort of “binding” that wires the views fields (in knockout a good example would be input or select tags) to the ViewModel properties. This makes maintainability easier because you could change some logic in the ViewModel property on how the data for the property is retrieved without the View knowing or caring about it. This is one less place for you to update. Often in software development, this concept is put under an umbrella called SoC or separation of concerns. Knockout does this by using the HTML5 data-bind attribute that all newer browsers understand and can be attached to any HTML tag. Knockout essentially looks for these tags and uses them to keep track of and update fields based on the users interaction. This makes your website much more responsive and creates a richer user experience. As I mentioned earlier, I will go into knockout much deeper in a future post.

The Use Case

A scenario was presented in our current project where we needed to retrieve data from an external source via an AJAX call and populate a dynamic table of checkboxes. This call was made based on the selection a user made from a dropdown list on the same screen. the data retrieved for these checkboxes was not huge, but it was big enough that I did not want to retrieve all the data up front when the page was loaded to sort through later. There are also security considerations that were taken into account as well. Since these checkboxes had to be rendered dynamically, the basic foreach and checkbox examples on knockout website. The issue I was encountering is that using the normal checkbox convention, there was no good way to keep track of the items that were selected by the user.

The Solution

I found the solution within the kockout documentation at the bottom of the checked section. This section refers to a checkedValue attribute that can be used  in conjunction with a knockout observable array to keep track of the items selected along with the value it of the checkbox. The documentation is here. I wouldn’t call it buried, but it is not completely obvious with dynamic checkboxes how to use it. There were a lot of out dated solutions for this using either older versions of knockout or what I would consider complete hacks. That is mainly why I wrote this blog.

The code that I ended up with to successfully accomplish my task looked like this:

 
<div data-bind="foreach: items">
   
 <input type="checkbox" data-bind="checkedValue: $data, checked: $root.chosenItems" /> <span data-bind="text: itemName"></span>
</div>
<br/>
<span>Selected Items</span>
<br/>
<div data-bind="foreach: chosenItems"> <div><span data-bind="text:itemName" /> </div>
  var viewModel = {
        items: ko.observableArray([{
            itemName: 'Choice 1'
        }, {
            itemName: 'Choice 2'
        }]),
        chosenItems: ko.observableArray()
    };

    ko.applyBindings(viewModel);

To see it in action, Check it out here. The meat of what I did here is in the following line of code:

<input type="checkbox" data-bind="checkedValue: $data, checked: $root.chosenItems" /> <span data-bind="text: itemName"></span>

The checkedValue as mentioned earlier is the value we want to persist. In this case $data is used because there is only one property (itemName) and knockout allows us to use this as a shorthand. The array that will be observed when the check event is raised is chosenItems. We use $root because the property is outside of the loop that you are currently in to create the checkboxes. $root and $parent allow you to traverse the property tree much like you can in other frameworks (such as JQuery). “items” is the list of items that are retrieved from some outside data source.

The last thing we do for testing purposes is loop through the items that are selected in the following code.

<div data-bind="foreach: chosenItems">
<div><span data-bind="text:itemName" />
</div>

Because chosenItems is an observerable, meaning that knockout tracks this item, every time the checkbox is selected and the list is updated, so is our little loop. All provided by knockout for free! Isn’t life grand!

 

Happy Coding my friends! Smile

Advertisements

About Gregg Coleman

I am Senior-level Software Engineer working primarily these days with .NET. I have a good working knowledge of ASP.NET MVC, Web Forms, WCF web services and Windows Services. I spend much of my time in the Web Services (SOAP and REST) world in my current job designing and implementing various SOA architectures. I have been in the software engineering industry for about 6 years now and will not now nor ever consider myself an "expert" in programming because there is always so much to learn. My favorite thing about designing software is there are always new emerging technologies and something to learn every day! My current job has me spending much of my job on the bleeding edge of technologies and changing gears all the time, so I'm never bored and always challenged. On my spare time I enjoy weight training, reading and venturing to new places near by. Of course programing and learning new technologies are another hobby of mine.
This entry was posted in MVVM, Web Technologies and tagged , , , , , , , , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s