Skip to main content Skip to footer

Populate Wijtree from External Data Source using Knockout

Since the introduction of Knockout as the official MVVM library, creating dynamic webpages has become a lot more easier. As you all must be aware that wijmo has adopted knockout as its official MVVM library, so you can build lightweight dynamic webpages using wijmo widgets with ease. In the following article I'll explain how you can populate wijtree from an external datasource (eg. WebService) using knockout.

Creating the View

The View is the same when binding it to an external data source as with declaring the nodes statically. This demo shows how to create the view for wijtree with knockout.

Creating ViewModel

Creating the ViewModel is not that difficult either. All we need to do is declare properties as knockout observables.

var viewModel = {  
   disabled: ko.observable(false),  
   allowTriState: ko.observable(true),  
   autoCheckNodes: ko.observable(true),  
   autoCollapse: ko.observable(true),  
   showCheckBoxes: ko.observable(true),  
   showExpandCollapse: ko.observable(true),  
   nodes: ko.observableArray([])  
};

One thing to note here is that nodes is declared as an empty array since it'll populated from the webservice.

Retrieving data and populating wijtree

This is somewhat tricky! At first I thought this would be easy, however, when I got to the implementation, it was not as easy as it looked! The tricky part here is that the nodes need to be in a hierarchy and we also need to make sure that the same nodes are not created multiple times. Now, to retrieve data from the webservice, we'll add a load method to the viewModel which would use the $.ajax jQuery method to make an asynchronous call to the webservice and fetch data. Below is the updated viewModel.

var viewModel = {  
   disabled: ko.observable(false),  
   allowTriState: ko.observable(true),  
   autoCheckNodes: ko.observable(true),  
   autoCollapse: ko.observable(true),  
   showCheckBoxes: ko.observable(true),  
   showExpandCollapse: ko.observable(true),  
   nodes: ko.observableArray([]),  
   load: function () {  
   $.ajax({  
      type: "POST",  
      url: "GetDetails.asmx/GetCityNames",  
      contentType: "application/json; charset=utf-8",  
      success: function (result) {  
         var data = result.d;  
         var dict1 = {};  
         var dict2 = {};  
         var arr = [];  

         //traverse data and populate arrays  
         $.each(data, function (i, elem) {  
            var d = data[i],  
            country = d.Country,  
            city = d.CityName;  
            region = d.Region;  

            //initialize new array for each country if it does not exist  
            if (!dict1[country]) {  
               dict1[country] = [];  
            }  

            //initialize new array for each country if it does not exist  
            if (!dict2[city]) {  
               dict2[city] = [];  
            }  

            dict2[city].push(new node(region));  

            if (dict1[country].length == 0) {  
               dict1[country].push(new node(city, dict2[city]));  
            }  
         });  

         //add nodes to array  
         $.each(dict1, function (key, value) {  
            arr.push(new node(key, value.length ? value : null));  
         });  
         viewModel.nodes(arr);  
         }  
      });  
   }  
};

The tricky part here is to make sure that the nodes that are nested do not get added repeatedly. Once an array for a Country is created, we need to add an array of Cities which in turn contains an array of Regions. Since, the nodes in wijtree must be an array, we need to create a class which would return a node and have a property 'nodes' of type array. Hence, we create the following class :

//create new node  
var node = function (Text, childNodes) {  
   return {  
   text: Text,  
   nodes: childNodes  
   }  
}

Lastly, we have to activate knockout and call the load() method of viewModel to bind wijtree to the viewModel.

$(document).ready(function () {  
   ko.applyBindings(viewModel, $(".container").get(0));  
   viewModel.load();  
});

This is how it'll appear :

Conclusion

Hope this article would be helpful for those looking for a way to populate wijtree with remote data. And not just wijtree, you can use this practically for any solution which requires remote data. You can download the sample below for the complete implementation. Note : You'll have to change the path of the service according to the server where you've hosted the service. Download Sample

MESCIUS inc.

comments powered by Disqus