Not sure if the post topic really explains what I'm trying to achieve - just exploring the possibilities of Razor, and trying to build out a simple site navigation.
I want it to work as below - if a page is selected at level 1, show its children. If a page is selected of those children, show that nodes' children.
Level 1 page Level 1 page Level 1 page (the first page selected - show its children) --- Level 2 page --- Level 2 page --- Level 2 page (the second page selected -show its children) ------ Level 3 page ------ Level 3 page --- Level 2 page Level 1 page Level 1 page Level 1 page Level 1 page Level 1 page
My current attempt is below - it works to build out the lists, but shows the entire nav tree - it should only show child nodes when the parent is selected. I guess what I need to do is build the nested lists, and as I add each item, check if it is an ancestor of the current page.
This would be ideal (item being the nav item being created, page the current page being served):
item.IsAncestorOrSelf(page)
My code (it's very much a rough run, surely someone can show me a much more robust way of achieving the same):
Hi. There's really a method called "IsAncestorOrSelf" (You can refer to the umbraco razor cheetsheet: http://our.umbraco.org/projects/developer-tools/razor-dynamicnode-cheat-sheet). In fact I'm not sure about its performance in case of large count of nodes since it's implemented via iterating through all descendants of the node in question. If you face performance problems with that inbuilt implementation you can fall back to simply using the "Path" property that returns the IDs of all ancestors and the ID of the node itself separated by a comma:
var isAncestorOrSelf = page.Path.Split(",").Contains(item.Id);
This method work well when you have small content tree or if result of your razor will be cached by OurputCache properly. Otherwise when tree very big IsAncestor lead to High CPU and Memory issue.
In our case we used it to build Main Navigation. By some reason this menu wasn't cached and IsAncestor load full content tree per each user request.
As result load test (Umbraco 6.1.6) show us that 30 concurent user kill our website, because memory grow from 800 MB to 4 GB, as result .net run GC more offen with max CPU utilizaition => performance issue.
To avoid performance issue use solution in first comment or use output cache.
Using the snippet mentioned above will return true if you check for ID 10 when f.ex. node id 100 is in the chain, or 2010. Right? You'd need to iterate the strings in the array and see if they really match. I'd use something like this instead:
public static bool IsAncestor(string path, int currentNode) { string[] nodes = path.Split(','); bool isAncestor = false;
foreach (string node in nodes) { if (node.Trim() == currentNode.ToString()) { isAncestor = true; break; } }
Check if ancestor of current node
Not sure if the post topic really explains what I'm trying to achieve - just exploring the possibilities of Razor, and trying to build out a simple site navigation.
I want it to work as below - if a page is selected at level 1, show its children. If a page is selected of those children, show that nodes' children.
Level 1 page
Level 1 page
Level 1 page (the first page selected - show its children)
--- Level 2 page
--- Level 2 page
--- Level 2 page (the second page selected -show its children)
------ Level 3 page
------ Level 3 page
--- Level 2 page
Level 1 page
Level 1 page
Level 1 page
Level 1 page
Level 1 page
My current attempt is below - it works to build out the lists, but shows the entire nav tree - it should only show child nodes when the parent is selected. I guess what I need to do is build the nested lists, and as I add each item, check if it is an ancestor of the current page.
This would be ideal (item being the nav item being created, page the current page being served):
My code (it's very much a rough run, surely someone can show me a much more robust way of achieving the same):
Hi. There's really a method called "IsAncestorOrSelf" (You can refer to the umbraco razor cheetsheet: http://our.umbraco.org/projects/developer-tools/razor-dynamicnode-cheat-sheet). In fact I'm not sure about its performance in case of large count of nodes since it's implemented via iterating through all descendants of the node in question. If you face performance problems with that inbuilt implementation you can fall back to simply using the "Path" property that returns the IDs of all ancestors and the ID of the node itself separated by a comma:
Ha, there you go... I think I'm still missing something though.
Using the example from part 7 of the Razor features walkthrough, I throw errors:
Where channel is the same variable as my first example (ie contains the ancestor nodes of the current node, excluding the root node).
Throws:
I'm on v5, if that makes a difference (I'm starting to think it might).
Hi, I recommend not use IsAncestor at all.
This method work well when you have small content tree or if result of your razor will be cached by OurputCache properly. Otherwise when tree very big IsAncestor lead to High CPU and Memory issue.
In our case we used it to build Main Navigation. By some reason this menu wasn't cached and IsAncestor load full content tree per each user request.
As result load test (Umbraco 6.1.6) show us that 30 concurent user kill our website, because memory grow from 800 MB to 4 GB, as result .net run GC more offen with max CPU utilizaition => performance issue.
To avoid performance issue use solution in first comment or use output cache.
Using the snippet mentioned above will return true if you check for ID 10 when f.ex. node id 100 is in the chain, or 2010. Right? You'd need to iterate the strings in the array and see if they really match. I'd use something like this instead:
is working on a reply...