I'm having datasource as follows
MenuID MenuName ParentMenuID
1 Self null
2 Functional null
3 Leave 1
4 Leave Application 3
5 Delete Application 4
I have formed kendo menu like,
@model IEnumerable<ESSUserInterface.Models.Menus>
<div>
@(Html.Kendo().Menu()
.Name("menu")
.Items(items =>
{
foreach (var item in Model)
{
if (item.ParentMenuID == null)
{
items.Add()
.Text(item.MenuName)
.Items(children =>
{
foreach (var subitem in Model)
{
if (subitem.ParentMenuID == item.MenuID)
{
children.Add().Text(subitem.MenuName)
.Items(innerchildren =>
{
foreach (var grandChilditem in Model)
{
if (grandChilditem.ParentMenuID == subitem.MenuID)
{
innerchildren.Add().Text(grandChilditem.MenuName);
}
}
});
}
}
});
}
}
})
.Direction(MenuDirection.Right)
)
</div>
But the above will work only with 3 levels, and menu ID 5 is not visible.
How can i solve this? I have tried few for loops, and nthng worked still.
11 Answers, 1 is accepted
The Menu supports binding to hierarchical data but the children should be included in the model. If the ParentMenuID is the only relation I can suggest to use recursion. Here is a sample that uses a recursive function defined in the view:
@
using
Kendo.Mvc.UI.Fluent
@functions{
public
void
addChildren(MenuItemBuilder builder, Menus item, IEnumerable<Menus> items){
var children = items.Where(m => m.ParentMenuID == item.MenuID);
if
(children !=
null
)
{
builder.Items(menuItems =>
{
foreach
(var child
in
children)
{
var menuItem = menuItems.Add().Text(child.MenuName);
addChildren(menuItem, child, items);
}
});
}
}
}
@(Html.Kendo().Menu()
.Name(
"menu"
)
.Items(menu => {
foreach
(var item
in
Model.Where(m=> m.ParentMenuID ==
null
))
{
var builder = menu.Add().Text(item.MenuName);
addChildren(builder, item, Model);
}
}))
Daniel
the Telerik team


how to bind custom route parameter runtime with Action propertiy.
Example: RouteParameter = " Status= False";
Any example on this.
I am not sure if I understand what you mean by "Action property". Could you clarify? If you are using the Action method then you can pass the route values after the action and controller names:
menu.Add().Text(item.MenuName).Action(
"action"
,
"controller"
,
new
{ Status =
false
})
Regards,
Daniel
Telerik
See What's Next in App Development. Register for TelerikNEXT.

Hi Daniel,
Actually I have to bind those route parameters at runtime not at design time.
my code is :
My parameters are like this: child .RouteParameters ="status=false&stage=user&menuData=123";
can you explain me how to achieve this.
public void addChildren(MenuItemBuilder builder, IEnumerable<Model> children)
{
//var children = items; //.Where(m => m.MainMenuId == mainMenuId);
if (children != null)
{
builder.Items(menuItems =>
{
foreach (var child in children)
{
var menuItem = menuItems.Add().Text(child.SubMenu);
if (child.RouteComponentCode > 0 )
{
menuItem.Action(child.RouteAction, child.RouteController, new { area = child.RouteArea, @status = child .RouteParameters});
}
addChildren(menuItem, Model.SubMenuModelEnumerable.Where(m => m.ParentId == child.SubMenuId));
}
});
}
}
}

Daniel,
Could you please post a sample of how to do this in the non-MVC-wrapper case? I am trying to build a simple Kendo Menu by reading data from the server via a rest url. I understand I can do this using the kendo.data.HierarchicalDataSource but cannot find a complete example anywhere.
My json data coming from server would look something like this
[{
"text":"Web Sites","url":"",
"children":
[{"text":"Google","url":"www.google.com","children":null},{"text":"Yahoo","url":"www.yahoo.com","children":null}]
}]
@Kiran
If you have the route values as string then you could parse it and set the resulting dictionary to the Action method:
foreach
(var child
in
children)
{
var menuItem = menuItems.Add().Text(child.SubMenu);
if
(child.RouteComponentCode > 0 )
{
var queryString = HttpUtility.ParseQueryString(child.RouteParameters);
var routeValues =
new
RouteValueDictionary();
foreach
(
string
key
in
queryString)
{
routeValues[key] = queryString[key];
}
routeValues[
"area"
] = child.RouteArea;
menuItem.Action(child.RouteAction, child.RouteController, routeValues);
}
}
@Hemant
The menu supports initialization from data when using the JavaScript initialization however the name of the children field should be items:
<
ul
id
=
"menu"
></
ul
>
<
script
>
$("#menu").kendoMenu({
dataSource: [{
"text":"Web Sites","url":"",
"items": [{
"text":"Google",
"url":"www.google.com",
"items":null
}, {
"text":"Yahoo",
"url":"www.yahoo.com",
"items":null
}]
}]
});
</
script
>
Regards,
Daniel
Telerik
See What's Next in App Development. Register for TelerikNEXT.

Hi Daniel,
Thank you for the sample, but I am looking how can use the encrypted route action parameters when I click on menu link?
any sample on this: use encryption parameter route values and redirect them to proper view in secure way?
Thanks,
Kiran
The menu does not provide any utilities for encrypting the parameters. This should be done the same way as in any other case.
Regards,
Daniel
Telerik
See What's Next in App Development. Register for TelerikNEXT.

This way working fine to load dynamic menu, but it is a performance hit on every time when we load master layouts, is there any other things need to care to control the performance?
Thanks,
Kiran
Probably, you are observing the non-cached security trimming functionality in action. Could you try to run the site in release mode and see whether performance issue is still observable? More details can be found here:
Regards,
Georgi Krustev
Telerik