For beginners, before reading this article, go through the interactive tutorial of knockout at: http://learn.knockoutjs.com/
The sample application posted here is about creating nested menu’s using the observableArray feature in knockout.js.
I had a requirement to create nested menus. To populate the menu names array, I had made an AJAX request. Since the menu names and the sub-menu names were dynamic data, I spent some time trying to get it work with ObservableArray object in Knockout. Thought would be of help for developers who are working on similar lines.
The objective of this article is to show how to use nested
ObservableArray of knockout to create nested menus. To keep the example simple, menu names are stored in global variables instead of making an AJAX request to get the menu names. Consider the global variables holding menu names as the data returned from AJAX call. The expected result is:
To start with, let’s create the global variables which hold the menu names:
familyNames" are the first level menu names:
subFamilyDataB" and "
subFamilyDataC" are the second level menu names.
sbB’ and "
sbC" are the third level menu names.
Let’s define the view model "Menu", "Submenu" and "Submenu2" representing the 3 level menus:
We have nested view models here. The hierarchy is as follows:
Menu -> SubMenu -> SubMenu2
To populate the submenu observableArray in Menu ViewModel lets define a function. The function
GetSubFamily is called on click of the menu.
GetSubFamily function, depending on the family selected or clicked in the UI, the local variable
subfamilydata gets initialized. For example, if the user selects
Family-A, the variable
subfamilydata is initialized to the global variable
subFamilyDataA. Then the data in the array
subfamilydata is pushed to the
submenu observable array.
The array data pushed to the
submenu observable array can be dynamic data returned from a web service.
To populate the
submenu2 observableArray in
SubMenu view model lets define the function. The function
fetchSubMenus is called on clicking the sub menu.
In the above two functions,
fetchSubMenus the observableArray is initialized with the data from the global variables. These data can be dynamic data returned from a web service.
Let’s define a main view model which has an observableArray filled with Menu objects.
MainViewModel has an observable array
AllProductsModel which holds objects of type Menu. The
MainViewModel has a function
AddProducts which pushes objects of the type Menu to observable array AllProductsModel.
Now that the view models are ready, let’s create the View and the bindings.
(The data-role & data-collapsed attributes from jQuery mobile are added to get the collapsible menu look and feel)
The MainViewModel instance is bound to the div with id-
familyDiv. AllProductsModel is an observableArray containing
Menu objects which is bound to the
div with command
foreach: AllProductsModel. Each Menu object contains an
observableArray submenu which is bound to the div
subFamilyDiv with command
foreach: submenu. Each
SubMenu object contains an observableArray
submenu2 is bound to
ul with command
The knockout will search for data-bind attribute and binds the data with its view.
On document ready:
Now when DOM is fully loaded, create an instance of the MainViewModel, call ko.applyBindings function and pass in the new instance created. The Menu objects are populated in AllProducts observableArray.
Ko.applyBindings activates knockout, and binds the view model to the view.
See this jsfiddle for the complete example: http://jsfiddle.net/2YCsN/67/