Knockout and Binding Lists

I have been using Knockout in an MVC project where I have been binding list-oriented data in the user interface.  I’ve been trying to use a more efficient approach to loading the UI by pushing the view with no data bound from the server, then following up with a subsequent request to serve up JSON, which populates the list.  This is the technique I’m focusing on in this article.  This means that the page builds an empty document model, then populates the model on document ready.  In my page, I build an empty view model:

function viewModel() {
var self = this;

self.listData = ko.observableArray([]);
}

Initially we start with an empty list.  At this point, on initial load, it’s beneficial to show something to the user that we have no data.  In order to do this, I found adding some computed properties for determining status was helpful.  These properties also existed in the model:

self.hasLoadedListData = ko.observable(false);
self.emptyListData = ko.computed(function() { return self.listData.length > 0; });

Here we have two properties, one for determining if we bound any data to the UI at all, and the second for determining whether the list is empty.  The difference between the two is that we may not want to show the list if there isn’t any data to bind; however, once we bound, we may want to instead show a “no records found” message, which the emptyListData property is used for.  Additionally, if we have no data to bind, and the observable points to a null value, we can get an exception too.  However, I’m going to shortly circumvent that by using the “if” binding.  In the user interface, we can setup the view to use these properties as so:

<div data-bind=”if:hasLoadedListData”>
<div data-bind=”if:emptyListData”>
No records found.
</div>
<div data-bind=”ifnot:emptyListData”>
<!– data template –>
</div>
</div>

Now it’s time to load the data.  Once data is passed to the model, it loads the view with the data at the time it’s populated.  I’m not going to get into the aspects of where the data comes from. Assuming we can get JSON from some data store, the JSON we would use, requested from JQuery, can then be passed to the view model, as in the following:

$.ajax({
type: “post”,
url: “…”,
data: { .. },
success: function(d) {
viewModel.itemData(d.Data); //array data in Data property
}
});

Here we get the data in JSON form, grab the array data from the Data property (as it’s recommended to return an object as the root object, not an array, for security purposes), and push it to the model.  There is an interesting point here; when we push the data in, the data in the array is not observable by its nature.  While this data would load into the user interface, any changes made to the values of the individual objects themselves are not observable and do not participate in two-way binding.  You could do a conversion like:

from (var i = 0, len = d.Data.length; i < len; i++)
{
viewModel.itemData.push({ firstName: ko.observable(d.Data[i].firstName), .. });
}

Through this conversion, each object is observable and participates in two-way binding.

Now that we have our data, it loads into the user interface, either through the observable templates as I blogged about before, or through an inline template.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s