Using KnockoutJS with Umbraco /base

It’s been a long time since my last blog-post and a lot has happened when it comes to learning new technologies, frameworks and common best-practices. Also, the solutions I’m building are getting bigger and more demanding when it comes to the great user experience both in the backend (Umbraco) and on the frontend.

When I attended CodeGarden ’11, I was introduced to a JavaScript library called KnockoutJS. As a former Silverlight and Surface developer, I found KnockoutJS interesting since it gives us the possibility to work with the MVVM pattern on the frontend of a website. Without writing a wall of text about how KnockoutJS works, i’d like to pinpoint some of the concepts and goods that this library gives us:

  • Declarative bindings: Easy ability to two-way bind elements using the data-bind=”" attribute.
  • Automatic UI updates: The UI changes whenever the viewmodels data changes.
  • Dependency tracking: Makes it possible to create relationship between model data.
  • Templating: Create templates to render the UI with the model data.

Last week I had the opportunity to make use of KnockoutJS in one of my clients Umbraco sites. The following scenario I’m going to show you in this blogpost is a fairly simple form to edit some details on a document. While this sounds simple, it was a challenge to work with a checkbox list because I had to populate the already chosen values in the list.

In this example I’m using:

First off, let’s have a look at the Document Type in Umbraco to get an overview of what data we’re working with (sorry about the danish names):

From top to bottom, freely translates: Title, Comments, Contact data, Description, Goals, Max. number of visitors, Course, Class, Knowledge center

Next, we’ll use Razor to populate the values into some HTML. You could use XSLT for this if you’re into that kind of gloomy business ;-)  Since my Razor file is about 130 lines I’m going to split it up a little. Explanation is in the code snippet. Here, we populate the Class checkbox list:

And next, a more simple snippet where we populate string values:

As you can see in the above snippets, we’re using the data-bind=”" attribute on elements. This tells KnockoutJS, that we’re trying to bind this element to a property on a viewmodel. I.e., in the second snippet we’re binding the input elements value to the contact and comments properties on our viewmodel. You can bind to just about any attribute and/or event an element have and you can even write your own binding handlers. In this case, we need to pass the values of the already selected checkboxes in our checkbox list to the viewmodel when the page is loaded. For this, we can create a custom binding handler which I will cover later.

Next, let’s have a look at the actual KnockoutJS viewmodel:

 

For those of you who have worked with Silverlight/WPF/Surface before, this snippet should be quite similar (though simpler) to a viewmodel in .NET terms. What happens here is fairly simple really: we declare our viewmodel and set the properties we need. When setting the properties, we need to set them to ko.observable(string) or ko.observableArray(). This will hook up dependency tracking to the property, which tells knockoutJS that it need to observe any change to this property. In .NET we can think of this as the INotifyPropertyChanged interface and the observableArray() as the ObservableCollection. So basically, everything (except the nodeId which comes from a hidden field) is hooked up to KnockoutJS in the viewmodel as observables – notice even the submit buttons click event is bound to the save property which sends off the viewmodels current state as JSON to the server using the ko.toJSON(viewmodel) function. We need to make a call to the ko.applyBindings(viewmodel) function afterwards to.. well.. apply the bindings ;-)

We still need to populate the already selected checkbox values to our checkbox list and store any changes to this. For this we can write our own binding handler (thanks to Ryan Niemeyer for clarification on this!)

Since the values are stored in an array, we’d like to get these values as a comma-seperated string for later use when updating the document. This can be done like this:

This sets a new property on the viewmodel with the comma-seperated string of values from the array.

We can now bind to this custom handler like this: <input data-bind=”classCheckedWithInit: selectedClassChoices” type=”checkbox” checked=”yes” value=’@pairs.Value’>@pairs.Key</input>

So now our complete viewmodel looks like this:

Whenever the client is changing any value, it will be reflected on the viewmodel (and thus any element that’s bound to the given property being changed) and as previously written, when the save event occurs, the whole viewmodel is being send to the server as JSON. For sending the data, we can use Umbracos /base functionality. In this example we’re making an ajax call to the SaveChanges.aspx page with the json object in the querystring (if anyone has got a better way of doing this, please let me know! :-) ) On the serverside, we’re going to use the JSON.NET from Newtonsoft to parse the json string to an actual object that we can get the values from. The base method looks like this:

In a perfect world, you would return a value to tell the client if the request succeeded or not, though ;-) Most important in this snippet is how to parse the string to a JSON object and pull the values from it.

Anyway, this turned in to a rather long wall of text. I’m sorry, guess I got carried away. I hope it makes sense though, even if it seems like a whole lot of work for something that simple I think the MVVM approach with KnockoutJS is a step in the right direction for making thick, responsive and intuitive frontends! And i’m definately not done learning all the cool stuff KnockoutJS gives us.

This entry was posted in JavaScript, jQuery, KnockoutJS, Umbraco CMS and tagged , , , . Bookmark the permalink. Post a comment or leave a trackback: Trackback URL.

Post a Comment

Your email is never published nor shared. Required fields are marked *

*
*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>


+ 6 = eleven