Reputation: 684
I am trying to show nested data in ul/li, but nested children are not showing. See my code and please tell me what is wrong there.
Controller:
public ActionResult Index()
{
List<MenuItem> allMenu = new List<MenuItem>
{
new MenuItem {Id=1,Name="Parent 1", ParentId=0},
new MenuItem {Id=2,Name="child 1", ParentId=1},
new MenuItem {Id=3,Name="child 2", ParentId=1},
new MenuItem {Id=4,Name="child 3", ParentId=1},
new MenuItem {Id=5,Name="Parent 2", ParentId=0},
new MenuItem {Id=6,Name="child 4", ParentId=4}
};
List<MenuItem> mi = allMenu
.Where(e => e.ParentId == 0) /* grab only the root parent nodes */
.Select(e => new MenuItem
{
Id = e.Id,
Name = e.Name,
ParentId = e.ParentId,
Children = allMenu.Where(x => x.ParentId == e.Id).ToList()
}).ToList();
ViewBag.menusList = mi;
return View();
}
POCO class:
public class MenuItem
{
public int Id { get; set; }
public string Name { get; set; }
public int ParentId { get; set; }
public virtual List<MenuItem> Children { get; set; }
}
View:
@helper ShowTree(List<Scaffolding.Controllers.MenuItem> menusList)
{
<ul>
@foreach (var item in menusList)
{
<li>
<span>@item.Name</span>
@if (item.Children != null && item.Children.Any())
{
@ShowTree(item.Children)
}
</li>
}
</ul>
}
@{
var menuList = ViewBag.menusList as List<Scaffolding.Controllers.MenuItem>;
@ShowTree(menuList);
}
If you run the code then you will see child 4 is not showing which is a child of child 3. Please advise what I need to change in my code. Thanks
Upvotes: 0
Views: 217
Reputation: 684
Now i could fix my problem. the problem was in logic of razor code and also i comment this line //.Where(e => e.ParentId == 0)
here i am adding working code.
@helper ShowTree(List<NestedChild.Controllers.MenuItem> menu, int? parentid = 0, int level = 0)
{
var items = menu.Where(m => m.ParentId == parentid);
if (items.Any())
{
if (items.First().ParentId > 0)
{
level++;
}
<ul>
@foreach (var item in items)
{
<li>
@item.Name
</li>
@ShowTree(menu, item.Id, level);
}
</ul>
}
}
@{
var menuList = ViewBag.menusList as List<NestedChild.Controllers.MenuItem>;
@ShowTree(menuList);
}
public ActionResult Index()
{
List<MenuItem> allMenu = new List<MenuItem>
{
new MenuItem {Id=1,Name="Parent 1", ParentId=0},
new MenuItem {Id=2,Name="child 1", ParentId=1},
new MenuItem {Id=3,Name="child 2", ParentId=1},
new MenuItem {Id=4,Name="child 3", ParentId=1},
new MenuItem {Id=5,Name="Parent 2", ParentId=0},
new MenuItem {Id=6,Name="child 4", ParentId=4}
};
List<MenuItem> mi = allMenu
//.Where(e => e.ParentId == 0) /* grab only the root parent nodes */
.Select(e => new MenuItem
{
Id = e.Id,
Name = e.Name,
ParentId = e.ParentId,
Children = allMenu.Where(x => x.ParentId == e.Id).ToList()
}).ToList();
ViewBag.menusList = mi;
return View();
}
Upvotes: 0
Reputation:
Your query gets the top level elements (ParentId == 0
) only and then populate just their direct child elements.
Your query needs to be changed to populate all child elements for all levels. Note that your MeuItem
does not need the ParentId
property.
// Group the items by parentId and project to MenuItem
var groups = allMenu.ToLookup(x => x.ParentId, x => new MenuItem
{
Id = x.Id,
Name = x.Name,
});
// Assign the child menus to all items
foreach (var item in allMenu)
{
item.children = groups[item.Id].ToList();
}
// Return just the top level items
ViewBag.menusList = groups[0].ToList();
As a side note, do not use ViewBag
. Pass the model to the view instead
return View(groups[0].ToList());
and in the view
@model List<MenuItem>
....
@ShowTree(Model);
Upvotes: 1