Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • Alex Skennerton 17 posts 179 karma points notactivated
    Jan 12, 2022 @ 17:28
    Alex Skennerton
    0

    Recursive menus

    Good afternoon,

    could someone please help me, I'm trying to create a recursive menu /list similar to the below for navigation:

    Section
    --a
    --b
    ----e
    ----f
    --------i
    --------j
    --------**K**
    ----------l
    ----------m
    ----g
    ----h
    --c
    --d
    

    where the user is at K and they can see what's below and what children there are of the direct ancestors of page.

    I'm sure this can be done recursively but I just can't seem to get that working and my long-form way of coding for each level is getting pretty ugly.

    I found something similar for asp.net on stackoverflow but just can't translate it across to Umbraco 9.

    My head is spinning with loops that just don't quite do it so any help would be greatly appreciated.

  • Alex Skennerton 17 posts 179 karma points notactivated
    Jan 18, 2022 @ 09:41
    Alex Skennerton
    100

    Every day is a school day, managed to work out how to do this using macros. The partial looks like this:

    @inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage
    
    @{
        var nodes = Model.AncestorOrSelf(2).Children().Where(x => x.IsVisible() && x.ContentType.Alias != "article");
    }
    
    <nav class="">
        <h2>Contents</h2>
        <ol class="">
            @if(nodes.Any())
                {
    
                    <ol class="">
                        <li class=""><a href="@Model.AncestorOrSelf(2).Url()" class="docNav active">@Model.AncestorOrSelf(2).Name</a></li>
                        @foreach(var node in nodes)
                        {
                            @await Umbraco.RenderMacroAsync("RecursiveMenu", new{nodeID = node.Id, currentModel = Model.Id});
                        }
                    </ol>
                }
        </ol>
    </nav>
    

    and the macro looks like this:

    @inherits Umbraco.Cms.Web.Common.Macros.PartialViewMacroPage
    
    
    @{
        int currentModelId = Model.GetParameterValue<int>("currentModel");
        var currentModel = Umbraco.Content(currentModelId);
    
        int nodeid = Model.GetParameterValue<int>("nodeID");
        var node = Umbraco.Content(nodeid);
        var childNodes = node.Children().Where(x => x.IsVisible() && x.ContentType.Alias != "article");
    
        var paddingLeft = (0.25 * node.Level);
    }
    
    <li style="padding-left:@(paddingLeft)rem;">
            <a href="@node.Url()" class="@(node.IsAncestorOrSelf(currentModel) ? "active" : null)">@node.Name</a>
            <ol class="">
                @foreach(var childNode in childNodes.Where(childNode => currentModel.IsDescendantOrSelf(node)))
                {
                    @await Umbraco.RenderMacroAsync("RecursiveMenu", new{nodeID = childNode.Id, currentModel = currentModel.Id});
                }
    
            </ol>
    
    </li>
    

    Hope this helps anyone else trying to do the same thing.

  • Carlos Mosqueda 244 posts 435 karma points
    Jan 18, 2022 @ 15:40
    Carlos Mosqueda
    1

    Nice job @Alex. Good solution to your issue. I like the padding trick. I have not seen that before.

  • Alex Skennerton 17 posts 179 karma points notactivated
    Jan 19, 2022 @ 10:16
    Alex Skennerton
    0

    Update: After checking my code for accessibility I found it was creating empty <ol> when there was no relevant child. So I've added a check to the loop first which removes this issue, please see below:

    Partial

    @inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage
    
    @{
        var nodes = Model.AncestorOrSelf(2).Children().Where(x => x.IsVisible() && x.ContentType.Alias != "article");
    }
    
    <nav class="">
        <h2>Contents</h2>
    
            @if(nodes.Any())
                {
    
                    <ol class="">
                        <li class=""><a href="@Model.AncestorOrSelf(2).Url()" class="docNav active">@Model.AncestorOrSelf(2).Name</a></li>
                        @foreach(var node in nodes)
                        {
                            @await Umbraco.RenderMacroAsync("RecursiveMenu", new{nodeID = node.Id, currentModel = Model.Id});
                        }
                    </ol>
                }
    
    </nav>
    

    And here is the Macro

    @inherits Umbraco.Cms.Web.Common.Macros.PartialViewMacroPage
    
    
    @{
        int currentModelId = Model.GetParameterValue<int>("currentModel");
        var currentModel = Umbraco.Content(currentModelId);
    
        int nodeid = Model.GetParameterValue<int>("nodeID");
        var node = Umbraco.Content(nodeid);
        var childNodes = node.Children().Where(x => x.IsVisible() && x.ContentType.Alias != "article" && currentModel.IsDescendantOrSelf(node));
    
        var paddingLeft = (0.25 * node.Level);
    }
    
    <li style="padding-left:@(paddingLeft)rem;">
            <a href="@node.Url()" class="docNav @(node.IsAncestorOrSelf(currentModel) ? "active" : null)">@node.Name</a>
    
            @if(childNodes.Any())
        {
            <ol class="">
                @foreach(var childNode in childNodes)
                {
                    @await Umbraco.RenderMacroAsync("RecursiveMenu", new{nodeID = childNode.Id, currentModel = currentModel.Id});
                }
    
            </ol>
        }
    
    </li>
    
Please Sign in or register to post replies

Write your reply to:

Draft