Background
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.
Sample application
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:
ViewModel:
To start with, let’s create the global variables which hold the menu names:
Variable "familyNames
" are the first level menu names:
Variables "subFamilyDataA
", "subFamilyDataB
" and "subFamilyDataC
" are the second level menu names.
Variables "sbA
", "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.
In the 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, GetSubFamily
and 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.
The 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.
View:
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 foreach: submenu2
.
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/