Knockout.js is great! I love the automatic UI refreshing that it does on the items that it has data bound. Not having to manually hookup these events saves a lot of time.
In the example below, I have a couple textboxes, a checkbox that initiates hiding or showing of the output, and there is also a button that removes the first name.
All of these are hooked up with this code pretty easily.
Check out the fiddle below:
This is great. The UI refreshes automatically!
The problem is that if you look at the data-bind attribute, you can see that that these are all magic strings that end up being the binding. If you have to change the model, there is no compile time checking that flags these as needing to be changed. You then have to do a find and replace and hope that you didn't inadvertently change text that was named similar.
What if I have to change the "lastName" in the model to be "surname" instead.
Yuck!
Searching around to see if there were better ways accomplish this and I was just unaware, I found a blog that has helpers to use with knockout to get that compile time checking.
It's called: Fluent Knockout Helpers.
I downloaded the helper from GitHub and installed it into my application.
To get this to work was pretty easy.
First, I set up my model:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace PlayWithKnockout.Models
{
public class Person
{
public string firstName { get; set; }
public string lastName { get; set; }
public bool removeFirstName { get; set; }
public bool nameVisible { get; set; }
}
}
Then I created my view:
@using FluentKnockoutHelpers.Core
@using PlayWithKnockout.Models
@model PlayWithKnockout.Models.Person
<script src="~/Scripts/knockout-2.2.1.js"></script>
<script src="~/Scripts/jquery-1.7.1.min.js"></script>
<script type="text/javascript">
$(function () {
var viewModel = {
firstName: ko.observable("Peter"),
lastName: ko.observable("Parker"),
removeFirstName: function () {
this.firstName("");
},
nameVisible: ko.observable(true)
};
ko.applyBindings(viewModel);
});
</script>
Old version with magic strings!
<br />
First Name: <input type="text" data-bind="value: firstName, valueUpdate: 'afterkeydown'" />
Last Name: <input type="text" data-bind="value: lastName, valueUpdate: 'afterkeydown'" />
<input type="checkbox" data-bind="checked: nameVisible" />
<p>
Hello, <span data-bind="text: firstName, visible: nameVisible"></span>
<span data-bind="text: lastName, visible: nameVisible"></span>
</p>
<button data-bind="click: removeFirstName">Remove first Name</button>
<br />
<br />
New version with compile time checking!
<br />
@{
var fkoPersonHelper = this.KnockoutHelperForType<Person>();
}
First Name: @fkoPersonHelper.BoundTextBoxFor(mm=>mm.firstName)
Last Name: @fkoPersonHelper.BoundTextBoxFor(mm=>mm.lastName)
<input type="checkbox" @fkoPersonHelper.DataBind(db=>db.Checked(person=>person.nameVisible)) />
<p>
Hello, <span @fkoPersonHelper.DataBind(db=>db.Text(person=>person.firstName).Visible(person=>person.nameVisible))></span>
<span @fkoPersonHelper.DataBind(db=>db.Text(person=>person.lastName).Visible(person=>person.nameVisible))></span>
</p>
<button @fkoPersonHelper.DataBind(db => db.Click(person => person.removeFirstName))>Remove first Name</button>
When I run the project it produces the view below:

This creates some nice compile time checking.
So now I can change the model from lastName to surname and it will throw an error for me.
Next up is to see if I can set the observables using the helper to reduce the javascript code. Stay tuned.
If you want more info on the helper itself, check out John's blog here...