Umbraco AncestorOrSelf(int) - what does it do?
Asked Answered
S

3

17

When using:

@Model.AncestorOrSelf(3)

In a .cshtml template in Umbraco, this would presumably limit the node traversal to 3 levels. Is this correct, and if so can anyone also confirm if the current node has the index zero?

Superficies answered 11/11, 2013 at 21:21 Comment(1)
I have updated my answer to explain more about your question with an example.Minimalist
M
37
@Model.AncestorOrSelf(3)

Model.Content is the current page that we're on. AncestorsOrSelf is all of the ancestors this page has in the tree. (level) means: go up to level 1/2/3/... and stop looking for more ancestors when you get there.

Above is the comment that you get with Umbraco 7.x rc version.

Take an example of the content tree below that is kind of similar to that you normally see in contents section in umbraco admin area:

Each content document has a level and by default it starts with 1.

In a .cshtml template in Umbraco, this would presumably limit the node traversal to 3 levels

As you can see in the example below, the level gets on increasing - level + 1. so, it starts by 1 and then just go on adding 1 to your sub levels.

- Content
 -- Home (level = 1)
   -- About Us (level = 2)
   -- Contact Us (level = 2)
   -- News Area (level = 2)
     -- News Item 1 (level = 3)
     -- News Item 2 (level = 3)
 -- Other Node (level = 1)

So when you mention 3 as parameter for AncestorOrSelf, you are asking to move to 3rd level in the tree from the current element that can be any document/partial view and stop looking for any more ancestors when its found.

AncestorOrSelf(level) returns a single item which if of type DynamicPublishContent i.e. you will have access to many properties like id, name, url, etc.

@CurrentPage.AncestorOrSelf(1)
// based on content structure above, the above statement will give you an item - Home.

It is basically for fetching ancestors by level, doesn't matter what your current level or currentpage object is.

For example, if you want to create a navigation in your main layout so as to share it on all pages of your site, you will do something like this in your template:

<ul>
 @foreach(var page in @CurrentPage.AncestorOrSelf(1).Children)
 {
   <li><a href="@page.Url">@page.Name</a></li>
 }
</ul>

Based on our example, it will give you:

About Us, Contact Us, News Area (in list form and with proper links)

Minimalist answered 12/11, 2013 at 11:49 Comment(3)
I've looked at this post numerous times over the months and just noticed that there isn't an Ancestor(), it's actually Ancestors() or AncestorsOrSelf(), etc - notice the "s" at the end of AncestorHomemaking
@RobScott i posted my answer in nov 2013. That member was available in the previous version. Maybe it has been changed over the time. do you use V6 or something else?Minimalist
You're right, sorry about that. I've been working on v6 at work and was looking at the cheat sheet. v7 does use singular. My apologies.Homemaking
L
0

Adding to the answer from SiddharthP I think the OP is possibly looking for the @CurrentPage.Up(int) method - this is traverses up the tree from the current level by the specified amount of levels.

So if you want the grandfather of the current node - @CurrentPage.Up(2) or @Model.Content.Up(2) for the strongly typed version.

Think of it as Ancestor starts from the root of the content tree down and Up starts from where you are going towards the root.

I think the confusing bit is you use the CurrentPage object but start traversing from the top root node towards the CurrentPage. When we think of our Ancestors in humanity we don't start from the beginning of time!

Latterll answered 16/1, 2015 at 9:47 Comment(1)
I believe there is a bug in v7.2 on the Up method. Just off to report it - use with caution!Latterll
E
-1

If my understanding of the code is correct, .AncestorOrSelf(int) returns the ancestor (or self) of a node at the given level in the argument.

Taken from lines 948 & 956 of https://github.com/umbraco/Umbraco-CMS/blob/6.2.0/src/umbraco.MacroEngines/RazorDynamicNode/DynamicNode.cs

public DynamicNode AncestorOrSelf(int level)
{
    return AncestorOrSelf(node => node.Level == level);
}

public DynamicNode AncestorOrSelf(Func<DynamicNode, bool> func)
{
    if (func(this)) return this;

    var content = this;
    while (content.Level > 1) // while we have a parent, consider the parent
    {
        // see note in .Parent - strange things can happen
        var parent = content.Parent;
        if (parent == content) return null;
        content = parent;

        if (func(content))
            return content;
    }

    return null;
}

Hope I've understood that correctly and that this helps.

Extramarital answered 12/11, 2013 at 10:30 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.