First steps with Knockout

As Knockout seems to be there by default with MVC4 and MVC5 and its creator is now working with Microsoft it seems wise to have a look at it and check how good it can be to go the MVVM way.

Installation

If you are using MVC.Net 4 or 5 it just comes by default so there isn’t anything else to do, else, you only need the library knockout.js and a call to it on your pages. Look for it on NuGet as it’s probably there.

Hello World

This is a simple example of how it works:

<body>

    <h1>Knockout</h1>

    <p>Your name: <input data-bind="value: firstName, valueUpdate: 'afterkeydown'" /></p>
    <h2>Hello, <span data-bind="text: firstName"> </span>!</h2>

    <script src="~/Scripts/knockout-2.2.0.js"></script>
    <script>
        var HelloWorldViewModel = function (name) {
            this.firstName = ko.observable(name);
        };

        ko.applyBindings(new HelloWorldViewModel("World"));
    </script>
</body>

First of all, you can see there the call to the knockout.js library, whithout which we can’t make it work. Also, I have declared a mini ViewModel for our HelloWorld example called “HelloWorldViewModel”, which is a function as in javascript classes are actually functions O_o

The function-class has only one property but that’s enough for this example, this one is declared as an “observable” property, which means that it will be “observing” what happens at the View and refreshing it instantly, this means that when some property in the Model changes every element bound to it will display the changes. You can see that if you make this example, as when you type on the input the name displayed below will be changed live.

Finally, to make that ViewModel work when the page loads we need to instantiate our object and call its “DoYourJobFuckingBastard!” method, which in knockout is the “applyBindings” one (also, we may prefer to do that inside the jQuery document.ready function, but that’s out of this example).

Why “applyBindings”? That’s the point of Knockout actually, notice that we have a property on the HTML tag elements that is a custom-property, or non HTML5 standard one, that property won’t affect our HTML code but will tell Knockout what to do, how, when, where, etc. It will tell it how to bind the Model with the View, and what’s more amazing, all that happens behind the scenes, so you don’t need to do that manually, just write the properties with the expected behaviour, declare the ViewModel and instantiate it and… voilá, it works. Without you needing to access the View directly from the “Controller” or the “Controller” needing to know anything about the View.

Also, in this example I’ve set “valueUpdate” to “afterkeydown“, this is to make the Model change on each keydown event of the input, by default Knockout will update the Model on focusout but I thought that the Hello World effect would look greater this other way, also you can see how to change that default updating behavior (if you don’t set the valueUpdate).

Dependency Injection

The ViewModel declaration/constructor doesn’t require to get any input but I added one (name) just to show that you can add any dependency in there to allow Dependency Injection (in this case the dependency is more imaginary).

A bit more of it

Let’s see now the ClickCounter example from Knockout’s website:

    <h2>KnockoutClickCounter</h2>

    <div>You've clicked <span data-bind="text: numberOfClicks"></span> times</div>
    <button data-bind="click: registerClick, disable: hasClickedTooManyTimes">Click me</button>

    <div data-bind="visible: hasClickedTooManyTimes">
        That's too many clicks! Please stop before you wear out your fingers.
        <button data-bind="click: resetClicks">Reset clicks</button>
    </div>

    <script src="~/Scripts/knockout-2.2.0.js"></script>
    <script>
        var ClickCounterViewModel = function() {
            this.numberOfClicks = ko.observable(0);

            this.registerClick = function() {
                this.numberOfClicks(this.numberOfClicks() + 1);
            }

            this.resetClicks = function() {
                this.numberOfClicks(0);
            }

            this.hasClickedTooManyTimes = ko.computed(function() {
                return this.numberOfClicks() >= 3;
            }, this);
        }

        ko.applyBindings(new ClickCounterViewModel());
    </script>

See how the object-class is declared without any injected dependency this time, we can also see some other binding keywords, like “click” to add a behavior on clicking the element, or “disable” to disable it when a condition is met.

Please, do notice how “disable” and “visible” work in this example, both of them will activate their behaviour when the condition is met, so that disable will disable the button and visible will make the div visible when “hasClickedTooMany” is true. That boolean is going to be updated on the Model by the two methods added to it and without telling to “update the view elements” it just will. That’s the Knockout binding system, doing the stuff behind the scenes and allowing you to focus on the logic and not on the manual job.

Leave a Reply

Close Bitnami banner
Bitnami