Unobtrusive Data-Binding for Knockout.js

Tags: knockout.js, data-binding, javascript

If you're a web developer who has yet to see Knockout, go take a look. I'll wait... Knockout is an incredible library, I just love it. Though I prefer to keep my presentation layer clean and now it's sprinkled with little bits of code for the data-binding. And that is how this Plugin came to be. It solves that problem with an easy way to Unobtrusively Data-Bind your presentation layer.

Obtrusive example (taken from knockoutjs.com)

You'll notice in this example, information about how to perform the data-binding is married to the presentation layer.

Choose a ticket class:
<select data-bind="options: tickets, 
                   optionsCaption: 'Choose...',
                   optionsText: 'name',
                   value: chosenTicket"></select> 

<p data-bind="template: 'ticketTemplate'"></p> 
        
<script id="ticketTemplate" type="text/x-jquery-tmpl"> 
    {{if chosenTicket}}
        You have chosen <b>${ chosenTicket().name }</b>
        ($${ chosenTicket().price })
        <button data-bind="click: resetTicket">Clear</button>
    {{/if}}
</script> 
    
<script type="text/javascript"> 
    var viewModel = {
        tickets: [
            { name: "Economy", price: 199.95 },
            { name: "Business", price: 449.22 },
            { name: "First Class", price: 1199.99 }
        ],
        chosenTicket: ko.observable(),
        resetTicket: function() { this.chosenTicket(null) }
    };
    ko.applyBindings(viewModel);
</script>	

Unobtrusive Example

But now the data-binding has been completely separated from the presentation layer.

<!-- file: ticket.html -->

Choose a ticket class:
<select id="tickets"></select> 

<p id="ticketOutput"></p> 
        
<script id="ticketTemplate" type="text/x-jquery-tmpl"> 
    {{if chosenTicket}}
        You have chosen <b>${ chosenTicket().name }</b>
        ($${ chosenTicket().price })
        <button data-bind="click: resetTicket">Clear</button>
    {{/if}}
</script> 

and the javascript file...

// file: ticket.js

var viewModel = {
    tickets: [
        { name: "Economy", price: 199.95 },
        { name: "Business", price: 449.22 },
        { name: "First Class", price: 1199.99 }
    ],
    chosenTicket: ko.observable(),
    resetTicket: function() { this.chosenTicket(null) }
};
 
$('#tickets').dataBind({
    options: 'tickets',
    optionsCaption: "'Choose...'",
    optionsText: "'name'",
    value: 'chosenTicket'
});
 
$('#ticketOutput').dataBind({ template: "'ticketTemplate'" });
 
ko.applyBindings(viewModel);

The Advantages / Why

Complete separation of code from your presentation layer -- There are many reasons why you might want this: Code can be kept in separate js files (think of caching), designers can now modify the html without worry of breaking it, etc. Elimination of magic strings-- Complex data-binding can be difficult to maintain with magic strings, especially when you start using functions or events. In the following example, I took the data-bound element from above and added a click event. Without the Unobtrusive approach, you'd have to encode that function into your magic string.

$('#tickets').dataBind({
    options: "tickets",
    optionsCaption: "'Choose...'",
    optionsText: "'name'",
    value: "chosenTicket",
    event: {
        change: function(evt) {
            console.log(evt);
        }
    }
});

Download it

Well that's pretty much it. The Plugin is small at only 544 bytes (360 bytes gzipped). Download it and play with it. Let me know if you find any bugs. You can download it here: github

Add a Comment