Animated Add & Remove with jQuery and Knockout

I’ve been doing so many cool things with jQuery and Knockout lately that have my developer soul bursting with glee. One of the things that I did most recently was to implement a small search application that allows a user to execute multiple searches and display the results as a collection of results. (That’s a little confusing. What I mean is that when you do one search, you get a box with the results. If you do another search, you get another box with another set of results.)

I wanted the interface to feel really fluid, and I figured the best way to do this would be to animate the appearance of the search results. I was using Knockout to databind results to the page, but this caused a problem: the results would appear on the page as soon as they were added to the collection.

Let’s look at an example of what I’m talking about so far:

var gcounter = 0;

var viewModel = function () {
    var self = this;
    self.items = ko.observableArray();
    
    self.add = function () {
        self.items.push(new itemViewModel("item " + ++gcounter));
    }
    
    self.remove = function (item) {
        self.items.remove(item);
    };
};

var itemViewModel = function(data) {
    var self = this;
    self.text = ko.observable(data);
};

ko.applyBindings(new viewModel());
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>

<div class="inline clickable" data-bind="click: add">
    <span class="ui-icon ui-icon-plus inline"></span>
    <span>Add</span>
</div>
<div data-bind="foreach: items">
    <div class="bigredbox clickable" data-bind="click: $parent.remove">
        <span class="ui-icon ui-icon-minus inline"></span>
        <span data-bind="text: text"></span>
    </div>
</div>

This example allows you to click ‘Add’ to add items, and remove items by clicking them. It’s very responsive, but it lacks a certain je ne sais quoi since items simply appear and disappear instantly. My first thought on addressing this was to make items fade into existence as they are added. We can do this in two steps. First, change the template for the data item to be hidden by default. Then, use jQuery to fade-in after the item is added to the collection. (Note that my hidden class contains just display: none and is defined in my css.)

var gcounter = 0;

var viewModel = function () {
    var self = this;
    self.items = ko.observableArray();
    
    self.add = function () {
        self.items.push(new itemViewModel("item " + ++gcounter));
        $(".bigredbox.hidden").fadeIn();
    }
    
    self.remove = function (item) {
        self.items.remove(item);
    };
};

var itemViewModel = function(data) {
    var self = this;
    self.text = ko.observable(data);
};

ko.applyBindings(new viewModel());
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>

<div class="inline clickable" data-bind="click: add">
    <span class="ui-icon ui-icon-plus inline"></span>
    <span>Add</span>
</div>
<div data-bind="foreach: items">
    <div class="bigredbox clickable hidden" data-bind="click: $parent.remove">
        <span class="ui-icon ui-icon-minus inline"></span>
        <span data-bind="text: text"></span>
    </div>
</div>

Ooh, that feels nice now, doesn’t it? But removing items still feels kinda lame. It would be really cool if items would fade away when they were removed! We can do that similarly to how we added the item. We need to employ a few tricks to make this happen, though. The click event’s second argument contains the control that was clicked in its target property. So, we can use event.target along with jQuery’s closest function to find the control we need to fade out. jQuery’s fadeOut method allows you to specify a callback to execute once it’s complete, so we’ll fade-out the selected item and remove it from the collection once the fade completes. That’s all we need to do, though; no HTML changes are needed.

var gcounter = 0;

var viewModel = function () {
    var self = this;
    self.items = ko.observableArray();
    
    self.add = function () {
        self.items.push(new itemViewModel("item " + ++gcounter));
        $(".bigredbox.hidden").fadeIn();
    }
    
    self.remove = function (item, event) {
        $(event.target).closest(".bigredbox").fadeOut(null, function() {
            self.items.remove(item);
        });
    };
};

var itemViewModel = function(data) {
    var self = this;
    self.text = ko.observable(data);
};

ko.applyBindings(new viewModel());

So that’s working great, but I still have a problem. When an item is removed, it fades away nicely, but then the results just flash together once the item disappears. It’d be nicer if that was also animated. jQuery’s slideUp method seems like it’d be perfect for this, so let’s just chain it together with fadeOut! Once again, there’s a little trick to this: you need to specify that the animations shouldn’t be queued. Luckily, that’s accomplished easily by specifying the correct option. Once again, this is a javascript-only change.

var gcounter = 0;

var viewModel = function () {
    var self = this;
    self.items = ko.observableArray();
    
    self.add = function () {
        self.items.push(new itemViewModel("item " + ++gcounter));
        $(".bigredbox.hidden").fadeIn();
    }
    
    self.remove = function (item, event) {
        $(event.target).closest(".bigredbox")
            .slideUp({queue: false})
            .fadeOut(null, function() {
                self.items.remove(item);
        });
    };
};

var itemViewModel = function(data) {
    var self = this;
    self.text = ko.observable(data);
};

ko.applyBindings(new viewModel());

Wooo, doggy! Now things are feeling very fluid. When we add an item, it fades into existence. Removing an item slides up and fades out. Everything feels really smooth and slick. Be sure to check out the jsfiddle for a working example!

Advertisement

Submit a Knockout-Bound jQuery Dialog when Enter is Pressed

There I was, happily coding an awesome logon prompt using the technique previously discussed here, when I ran into a problem: my form wasn’t submitting when I pressed the ‘enter’ key. That’s annoying. No self-respecting logon prompt should require you to move the mouse to a button and click!

So what to do?! Step one: don’t panic. Okay, good. Now you can use a few easy tricks to force the dialog to submit when enter is pressed.

Let’s look at the example that doesn’t work. I have a simple Knockout view model hooked up to a jQuery dialog. When I click the dialog’s “Login” button, it calls a login function. If I press the enter key, though, nothing happens. I take that back; one thing happens: you become annoyed that nothing happened.

var loginViewModel = function() {
    var self = this;
    self.password = ko.observable();
    self.username = ko.observable();
};

$("#loginDialog").dialog({
    buttons: {
        "Login": login
    }
});

function login() {
    // login stuff
}
<div id="loginDialog" title="Login">
    <form id="loginForm">
        <fieldset>
            <label for="user">Username</label>
            <input type="text" id="user" data-bind="value: username" />
            <label for="password">Password</label>
            <input type="password" id="password" data-bind="value: password" />
        </fieldset>
    </form>
</div>

The first thing we need to do is to bind our form to our view model using Knockout’s submit binding. With the submit binding in place, we can use jQuery to submit the form.

var loginViewModel = function() {
    var self = this;
    self.password = ko.observable();
    self.username = ko.observable();
    self.login = function() {
        // login stuff
    };
};

$("#loginDialog").dialog({
    buttons: {
        "Login": function () {
            $("#loginForm").submit();
        }
    }
});
<div id="loginDialog" title="Login">
    <form id="loginForm" data-bind="submit: login">
        <fieldset>
            <label for="user">Username</label>
            <input type="text" id="user" data-bind="value: username" />
            <label for="password">Password</label>
            <input type="password" id="password" data-bind="value: password" />
        </fieldset>
    </form>
</div>

Now we’re equipped to handle the enter keypress. So let’s do that…

var loginViewModel = function() {
    var self = this;
    self.password = ko.observable();
    self.username = ko.observable();
    self.login = function() {
        // login stuff
    };
};

$("#loginDialog").dialog({
    buttons: {
        "Login": function () {
            $("#loginForm").submit();
        }
    }
});
$("#loginDialog").keypress(function(event) {
    if (event.which == 13) {
        event.preventDefault();
        $("#loginForm").submit();
    }
});

That might seem like that should be it, but it’s not quite working. It seems to submit just fine, but login only succeeds when the button is pressed. What gives!? It’s a subtle thing that took me a little bit of time to realize. Databound values are only updated by default when focus leaves the control. So, if you enter a username, press tab, enter a password, then press enter, the password value in the view model hasn’t been updated yet! Argh!

No problem, though. We can change the value to update with each keypress.

<div id="loginDialog" title="Login">
    <form id="loginForm" data-bind="submit: login">
        <fieldset>
            <label for="user">Username</label>
            <input type="text" id="user" data-bind="value: username, valueUpdate: 'afterkeydown'" />
            <label for="password">Password</label>
            <input type="password" id="password" data-bind="value: password, valueUpdate: 'afterkeydown'" />
        </fieldset>
    </form>
</div>

Now we’re in business! The login works great whether you press the button or use the enter key.

Databinding Collections with Knockout

I’ve written a few articles about databinding using Knockout (here, here, and here), but I haven’t touched on collections yet. Collections have proved to be a little more challening and require a bit more work, but they still follow the same pattern.

In this post, I’ll work through a short example to demonstrate how to do two-way databinding with collection objects.

Create Your View Models

I’ve found that getting a collection to bind properly requires multiple view models. The applications that I’ve written have required a main, page-level view model and separate models for each item in the collection.

Let’s say we want to write an page that will manage a classroom roster. The primary model will be called rosterViewModel, and we’ll create another model to represent students, studentViewModel. When the page is initialized, we’ll create a new instance of rosterViewModel and bind it to the page using Knockout.

var rosterViewModel = function() {
    var self = this;
    self.students = ko.observableArray();
};

var studentViewModel = function() {
    var self = this;
    self.firstName = ko.observable();
    self.lastName = ko.observable();
};

ko.applyBindings(new rosterViewModel());

Allow Items to be Added

Adding new items to the databound collection is as easy as creating a new instance of the sub-item’s view model and adding it to the collection. This should be done in an event handler of the parent model. So, in our example, we’ll add an addStudent event that will add a new instance of studentViewModel to the students collection.

var rosterViewModel = function() {
    var self = this;
    self.students = ko.observableArray();
    self.addStudent = function() {
        self.students.push(new studentViewModel());
    };
};

Allow Items to be Removed

Removing items from the collection works the same way as adding. When the event is invoked from the item to be removed, you simply remove it from the collection. We create another event, removeStudent, that does this.

var rosterViewModel = function() {
    var self = this;
    self.students = ko.observableArray();
    self.addStudent = function() {
        self.students.push(new studentViewModel());
    };
    self.removeStudent = function(student) {
        self.students.remove(student);
    };
};

Populating the Collection

Populating the collection might seem like a no-brainer. You’ve got some data, just pass it to Knockout and let it do its job, right? That actually works okay if you’re not modifying the data. The problem is that the source data isn’t rigged for Knockout with ko.observables and ko.observableArrays. The result is that data populates, but changes aren’t detected.

What I’ve done to get around this is to loop through the source collection, instantiate the appropriate view model object, and add it to the parent model’s collection. To make things easier, I modify the view model to accept the source data as an input and populate properties when it’s provided.

var rosterViewModel = function(data) {
    var self = this;
    self.students = ko.observableArray();
    self.addStudent = function() {
        self.students.push(new studentViewModel());
    };
    self.removeStudent = function(student) {
        self.students.remove(student);
    };
    
    if (data != null) {
        var s = data.students;
        for (var i in s) {
            self.students.push(new studentViewModel(s[i]));
        }
    }
};

var studentViewModel = function(data) {
    var self = this;
    self.firstName = ko.observable();
    self.lastName = ko.observable();
    
    if (data != null) {
        self.firstName(data.firstName);
        self.lastName(data.lastName);
    }
};

var sourceData = {
    students: [{ firstName: "Adam", lastName: "Prescott" }]
};

ko.applyBindings(new rosterViewModel(sourceData));

Retrieving the Collection

If you need to retrieve your collection for processing, I suggest doing the opposite of what was done to populate the collection: loop through the view model and extract the data. What you do with the data is up to you. You can package it into another object to be sent to another service or method, or format it for display elsewhere on the page. To demonstrate, I created a computed property that creates an HTML list of students entered.

self.roster = ko.computed(function() {
    var result = "Students:<br/>";
    var s = self.students();
    for (var i in s) {
        var f = s[i].firstName() ? s[i].firstName() : "&lt;unknown&gt;";
        var l = s[i].lastName() ? s[i].lastName() : "&lt;unknown&gt;";
        result += l + ", " + f + "<br/>";
    }
    return result;
});

You can see the complete working example here.

Real-time Validation with Knockout

Knockout gives you a slick way to do real-time validation on your data with its built-in extenders. At first glance, it may not seem like an entirely intuitive process, but it’s actually pretty clever. When you use an extender, you’re extending the property to have additional sub-properties and behaviors. Makes sense, right?

Let’s look at a simple example: validating a date value.

We begin by creating a simple view model and UI.

var viewModel = function () {
    var self = this;
    this.dateValue = ko.observable();
};
ko.applyBindings(new viewModel());
<div>
    <input data-bind="value: dateValue" />
</div>

Now we can create our extender. We introduce a new hasError property that we’ll bind to the UI and use to show & hide validation messages. There’s a validate function that contains the validation logic. The validate method is called to perform the initial validation, and subscribe is called so that validate will be called when the value changes. Note that we also add valueUpdate: ‘afterkeydown’ to the input data-binding. This allows the validation to perform after each keystroke.

var viewModel = function () {
    var self = this;
    this.dateValue = ko.observable().extend({
        validDate: true
    });
};

ko.extenders.validDate = function (target) {
    target.hasError = ko.observable();

    function validate(value) {
        var invalid = isNaN(Date.parse(value));
        target.hasError(invalid);
    }

    validate(target());
    target.subscribe(validate);
    return target;
};

ko.applyBindings(new viewModel());
<div>
    <input data-bind="value: dateValue, valueUpdate: 'afterkeydown'" />
    <span data-bind="visible: dateValue.hasError">Invalid!</span>
</div>

That’s it for the hard stuff. All that’s left is to figure out what should be shown or hidden when the value is invalid or valid. I chose to show an alert icon and added some CSS to make the input box red.

.invalid input {
    border: 1px solid red;
}
.ui-icon {
    display: inline-block;
    vertical-align: middle;
}
<div data-bind="css: { invalid: dateValue.hasError }">
    <input data-bind="value: dateValue, valueUpdate: 'afterkeydown'" />
    <span class="ui-icon ui-icon-alert" title="Invalid value" data-bind="visible: dateValue.hasError"></span>
</div>

Check out this Fiddle for the working example.

Posting Data to an ASP.NET Page Method with Knockout

PostingDataToPageMethodWithKnockoutSample

Last time in my Knockout series of posts, I explored how to retrieve and bind data from an ASP.NET page method. That’s only half the battle, though. How can you take data captured and do interesting things with it? I’ve got an idea! How about passing it to an ASP.NET page method!

I’m going to use my example from last time with a few modifications. I added some entry controls to capture the user’s status, and I modified the GetStatus page method to return the user’s last status. The last status values will be displayed as read-only and will only be visible when a value exists. Here’s the ASPX and code-behind. Note that ASPX contains a button bound to a method in the view model that’s not yet implemented, and the code-behind has a UpdateStatus method.

default.aspx:

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="adamprescott.net.Knockout.Default" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
    <script src="Scripts/jquery-2.0.2.min.js"></script>
    <script src="Scripts/knockout-2.2.1.js"></script>
    <script type="text/javascript">
        $(function () {
            var viewModel = {
                wasHappy: ko.observable(),
                lastStatusText: ko.observable(),
                isCurrentlyHappy: ko.observable(),
                currentStatusText: ko.observable(),
                updateStatus: updateStatus,
            };
            ko.applyBindings(viewModel);
            getLastStatus();

            function updateStatus() {
                // todo: post data to page method
            }

            function getLastStatus() {
                $.ajax({
                    type: "POST",
                    url: "Default.aspx/GetStatus",
                    data: "{}",
                    contentType: "application/json; charset=utf-8",
                    dataType: "json",
                    success: function (result) {
                        var data = result.d;
                        if (data == null) {
                            $("#lastTime").hide();
                            return;
                        }
                        $("#lastTime").show();
                        viewModel.wasHappy(data.HappyFlag);
                        viewModel.lastStatusText(data.Text);
                    }
                });
            }
        });
    </script>
</head>
<body>
    <div>
        <strong>How are you feeling?</strong><br/>
        Are you happy? <input data-bind="checked: isCurrentlyHappy" type="checkbox"/><br/>
        Tell me about it: <input data-bind="value: currentStatusText"/><br/>
        <button data-bind="click: updateStatus">Update Status</button>
    </div>
    <div id="lastTime">
        <strong>How you felt last time:</strong><br/>
        Were you happy? <input data-bind="checked: wasHappy" type="checkbox" disabled="true"/><br/>
        What you told me about it: <span data-bind="text: lastStatusText"></span>
    </div>
</body>
</html>

default.aspx.cs:

using System;
using System.Web.Services;

namespace adamprescott.net.Knockout
{
    public class Status
    {
        public bool HappyFlag { get; set; }
        public string Text { get; set; }
    }

    public partial class Default : System.Web.UI.Page
    {
        private static Status lastStatus = null;

        [WebMethod]
        public static Status GetStatus()
        {
            return lastStatus;
        }

        [WebMethod]
        public static void UpdateStatus(Status status)
        {
            lastStatus = status;
        }
    }
}

When the button is pressed, we need to collect values and put them into an object to be passed to our page method. That’s easy–just grab values from the view model:

var data = {};
data.HappyFlag = viewModel.isCurrentlyHappy();
data.Text = viewModel.currentStatusText();

Now that we’ve got our values, we just need to pass them to our page method. Once again, it’s jQuery to the rescue!

$.ajax({
    type: "POST",
    url: "Default.aspx/UpdateStatus",
    data: JSON.stringify({ 'status': data }),
    contentType: "application/json; charset=utf-8",
    dataType: "json",
    success: function () {
        // todo: anything?
    }
});

Bam! We just passed data to the page method in the code-behind. Tutorial accomplished. However, I need to go a little further. Now that I just updated the status, I want my UI to update its view to show the latest status. So, when my call to UpdateStatus finishes successfully, I just need to make another call to GetStatus. Super easy!

Here’s the final ASPX.

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="adamprescott.net.Knockout.Default" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
    <script src="Scripts/jquery-2.0.2.min.js"></script>
    <script src="Scripts/knockout-2.2.1.js"></script>
    <script type="text/javascript">
        $(function () {
            var viewModel = {
                wasHappy: ko.observable(),
                lastStatusText: ko.observable(),
                isCurrentlyHappy: ko.observable(),
                currentStatusText: ko.observable(),
                updateStatus: updateStatus, 
            };
            ko.applyBindings(viewModel);
            getLastStatus();

            function updateStatus() {
                // todo: post data to page method
                return;
                var data = {};
                data.HappyFlag = viewModel.isCurrentlyHappy();
                data.Text = viewModel.currentStatusText();
                $.ajax({
                    type: "POST",
                    url: "Default.aspx/UpdateStatus",
                    data: JSON.stringify({ 'status': data }),
                    contentType: "application/json; charset=utf-8",
                    dataType: "json",
                    success: function () {
                        getLastStatus();
                    }
                });
            }

            function getLastStatus() {
                $.ajax({
                    type: "POST",
                    url: "Default.aspx/GetStatus",
                    data: "{}",
                    contentType: "application/json; charset=utf-8",
                    dataType: "json",
                    success: function (result) {
                        var data = result.d;
                        if (data == null) {
                            $("#lastTime").hide();
                            return;
                        }
                        $("#lastTime").show();
                        viewModel.wasHappy(data.HappyFlag);
                        viewModel.lastStatusText(data.Text);
                    }
                });
            }
        });
    </script>
</head>
<body>
    <div>
        <strong>How are you feeling?</strong><br/>
        Are you happy? <input data-bind="checked: isCurrentlyHappy" type="checkbox"/><br/>
        Tell me about it: <input data-bind="value: currentStatusText"/><br/>
        <button data-bind="click: updateStatus">Update Status</button>
    </div>
    <div id="lastTime">
        <strong>How you felt last time:</strong><br/>
        Were you happy? <input data-bind="checked: wasHappy" type="checkbox" disabled="true"/><br/>
        What you told me about it: <span data-bind="text: lastStatusText"></span>
    </div>
</body>
</html>

Databinding from an ASP.NET Page Method with Knockout

Last week, I wrote a brief post about how easy it is to do databinding with Knockout. The article presents a barebones example, but it fails to address an important issue: how to get data into the view model.

I live in a .NET world, and I’m usually working with small ASP.NET application. I’ve found that page methods are an easy and convenient way to get to the data I need. They’re easily accessible via jQuery, too. So let’s see how we can get data from an ASP.NET page method using jQuery and pass it along to our Knockout view model.

First, let’s get to know our page method. I created a simple Status class that will be returned from a page method, GetStatus. Here’s the entire code-behind for my page:

using System;
using System.Web.Services;

namespace adamprescott.net.Knockout
{
    public class Status
    {
        public bool HappyFlag { get; set; }
        public string Text { get; set; }
    }

    public partial class Default : System.Web.UI.Page
    {
        [WebMethod]
        public static Status GetStatus()
        {
            return new Status { HappyFlag = true, Text = "This just a default" };
        }
    }
}

We know what data we’re getting, so we can go ahead and create our view model and UI. Here’s what that looks like:

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="adamprescott.net.Knockout.Default" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
    <script src="Scripts/jquery-2.0.2.min.js"></script>
    <script src="Scripts/knockout-2.2.1.js"></script>
    <script type="text/javascript">
        $(function () {
            var viewModel = {
                isHappy: ko.observable(),
                statusText: ko.observable(),
            };
            ko.applyBindings(viewModel);
            
            // todo: get data from page method
        });
    </script>
</head>
<body>
    <input data-bind="value: statusText" /><br/>
    Happy? <input data-bind="checked: isHappy" type="checkbox" />
</body>
</html>

All that’s left is for us to do is call the page method and update the values in our view model. And, as I said before, jQuery makes it a snap!

$.ajax({
    type: "POST",
    url: "Default.aspx/GetStatus",
    data: "{}",
    contentType: "application/json; charset=utf-8",
    dataType: "json",
    success: function (result) {
        var data = result.d;
        viewModel.isHappy(data.HappyFlag);
        viewModel.statusText(data.Text);
    }
});

With that, we’re done. When the page loads, the view model is created and bound to the UI controls. We then make an asynchronous call to the page method using jQuery and update the values in our view model.

Here’s the complete ASPX file:

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="adamprescott.net.Knockout.Default" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
    <script src="Scripts/jquery-2.0.2.min.js"></script>
    <script src="Scripts/knockout-2.2.1.js"></script>
    <script type="text/javascript">
        $(function () {
            var viewModel = {
                isHappy: ko.observable(),
                statusText: ko.observable(),
            };
            ko.applyBindings(viewModel);
            
            $.ajax({
                type: "POST",
                url: "Default.aspx/GetStatus",
                data: "{}",
                contentType: "application/json; charset=utf-8",
                dataType: "json",
                success: function (result) {
                    var data = result.d;
                    viewModel.isHappy(data.HappyFlag);
                    viewModel.statusText(data.Text);
                }
            });
        });
    </script>
</head>
<body>
    <input data-bind="value: statusText" /><br/>
    Happy? <input data-bind="checked: isHappy" type="checkbox" />
</body>
</html>

Two-Way Databinding with Knockout

Earlier this week, I wrote a post about two-way databinding with jQuery. I was looking for a fast & elegant way to do it, but I came up somewhat empty. A lot of what I was finding suggested using a different plug-in or framework, such as Knockout. I decided to give Knockout a whirl, and I’m an instant fan.

My favorite part is how the binding occurs declaratively in the HTML.

<input data-bind="checked: boolValue" type="checkbox" />
<input data-bind="value: textValue" />

That’s all you need to bind the values to the controls–nice, right!? Okay, but this is javascript, so what’s going on at the top? Surely, it’s a mess. Nope, it’s just as easy. Just create a view model and call Knockout’s applyBindings method.

var viewModel = {
    boolValue: ko.observable(true),
    textValue: ko.observable("Hello!")
};
ko.applyBindings(viewModel);

That’s it, I promise. To show that there’s nothing up my sleeve, here’s the entire page:

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
    <script src="Scripts/jquery-2.0.2.min.js"></script>
    <script src="Scripts/knockout-2.2.1.js"></script>
    <script type="text/javascript">
        $(function () {
            var viewModel = {
                boolValue: ko.observable(true),
                textValue: ko.observable("Hello!")
            };
            ko.applyBindings(viewModel);
        });
    </script>
</head>
<body>
    <input data-bind="checked: boolValue" type="checkbox" />
    <input data-bind="value: textValue" />
    
    <div>The value of boolValue is <span data-bind="text: boolValue"></span></div>
    <div>The value of textValue is <span data-bind="text: textValue"></span></div>
</body>
</html>

The Knockout site has really good interactive tutorials for getting started. If you’re interested in learning or exploring further, definitely start there.

%d bloggers like this: