Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / Javascript

Nested menu’s creation using nested ObservableArray’s of Knockout.js

0.00/5 (No votes)
10 Sep 2013CPOL3 min read 16.6K  
Nested menu’s creation using nested ObservableArray’s of Knockout.js

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:

Image 1

ViewModel:

To start with, let’s create the global variables which hold the menu names:

Variable "familyNames" are the first level menu names:

Image 2

Variables "subFamilyDataA", "subFamilyDataB" and "subFamilyDataC" are the second level menu names.

Image 3

Variables "sbA", "sbB and "sbC" are the third level menu names.

Image 4

Let’s define the view model "Menu", "Submenu" and "Submenu2" representing the 3 level menus:

Image 5

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.

Image 6

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.

Image 7

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.

Image 8

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.

Image 9

(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.

Image 10

See this jsfiddle for the complete example: http://jsfiddle.net/2YCsN/67/

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)