Copied to clipboard

Flag this post as spam?

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


  • Mike 62 posts 274 karma points
    Jul 15, 2013 @ 12:20
    Mike
    0

    Using Razor to create a push-down sub navigation

    Hi everyone,

    I'm battling to get my head around a navigation issue with Razor. I have a top level navigation which uses JQuery to present the user with a push-down menu should the parent node have children to show. If it doesn't then the link clicks through to the page as normal.

    If the main menu item does have children then I've added a "data-panel" value to the a tag so that the JQuery can decide which sub navigation block to show in the push-down:

    @if (item.Children.Where("Visible").Count() > 0) {
          <a href="@item.Url" title="@item.Name" data-panel="@item.Name.ToLower().Replace(" ", "")">@item.Name</a>
    } else {
          <a href="@item.Url" title="@item.Name">@item.Name</a>
    }

    This works fine. So now I have to build the sub-navigation razor script and this is where I'm struggling. The sub nav is built using a series of <nav> blocks for each parent. So let's say I have:

    Parent Menu 1    |    Parent Menu 2    |    Parent Menu 3

    There would be a separate <nav> block for each parent (if they have children) which would list all the children in nested list items a bit like a sitemap. So an example of a nav block would be:

    <nav class="subnav panel-parentmenu1">
        <header>
            <h1><a href="#" title="">Parent Menu 1 (Show the parent menu as a link)</a></h1>
        </header>
        <ul>
            <li>
                <a href="#" title="">Child page 2nd level</a>
                <ul>
                    <li><a href="#" title="">Child page 3rd level</a></li>
                    <li><a href="#" title="">Child page 3rd level</a></li>
                    <li><a href="#" title="">Child page 3rd level</a></li>
                </ul>
            </li>
            <li>
                <a href="#" title="">Another child page 2nd level</a>
                <ul>
                    <li><a href="#" title="">It's child pages at 3rd level</a></li>
                    <li><a href="#" title="">It's child pages at 3rd level</a></li>
                    <li><a href="#" title="">Etc</a></li>
                </ul>
            </li>
        </ul>
    </nav>

    and then Parent Menu 2 would be the same if it has children...

    <nav class="subnav panel-parentmenu2">
        <header>
            <h1><a href="#" title="">Parent Menu 2 (Show the parent menu as a link)</a></h1>
        </header>
        <ul>
            etc... and so on...

    My first instinct is to base the razor on a sitemap as the sub nav contents would be the same regardless of what page the user is on, but I really only want to create one razor script to handle all the sub nav blocks as needed but my Razor isn't good enough yet to get me past first base in the process.

    Does anyone have any ideas on how I could put this together?

    Many thanks,
    Mike

  • Fuji Kusaka 2203 posts 4220 karma points
    Jul 15, 2013 @ 12:36
    Fuji Kusaka
    0

    Hi Mike,

    What you could eventually do is get it to check if any child node is present and if its not Hidden.

    var show = (item.Children.Where("umbracoNaviHide != true").count() > 0)? "data-panel=": ""; // true : false 
       <a href="@item.Url" title="@item.Name" @show>@item.Name</a>

    Hope this helps

    //fuji

  • Mike 62 posts 274 karma points
    Jul 15, 2013 @ 17:04
    Mike
    0

    Hey Fuji, thanks very much for the reply. So this is what I have working thus far:

    @inherits umbraco.MacroEngines.DynamicNodeContext

    <div class="top">
        <header class="logo">
            <h1><a href="/"><img src="/images/logo.png" /></a></h1>
        </header>
        <nav class="mainmenu">
            <!-- Display mobile menu icon when needed -->
    <div class="menuicon"><a href="" title=""><img src="/images/menuicon.png" alt="" title=""></a></div>
            <!-- end // -->

    <!-- write out parent menus for non-mobile displays. -->
            @{
            var level = String.IsNullOrEmpty(Parameter.Level) ? 1 : int.Parse(Parameter.Level);
            var ulClass = String.IsNullOrEmpty(Parameter.UlClass) ? "" : String.Format(" class=\"{0}\"", Parameter.UlClass);
            var parent = @Model.AncestorOrSelf(level);
            if (parent != null) {
                <[email protected](ulClass)>
                    @foreach (var item in parent.Children.Where("Visible")) {
                        var selected = Array.IndexOf(Model.Path.Split(','), item.Id.ToString()) >= 0 ? " class=\"selected\"" : "";
                        <[email protected](selected)>
    <!-- now check if parent menu has any children -->
    <!-- If so add data-panel to a tag with name of parent. If not just write out normal a tag -->
                            @if (item.Children.Where("Visible").Count() > 0) {
                                <a href="@item.Url" title="@item.Name" data-panel="@item.Name.ToLower().Replace(" ", "")">@item.Name</a>
                            } else {
                                <a href="@item.Url" title="@item.Name">@item.Name</a>
                            }
    <!-- end // -->
                        </li>
                    }
                </ul>
                }
            }
    <!-- end parent menus // -->
        </nav>
        <div class="clearfix"><!--//--></div>
    </div>

    <!-- pushdown menu for mobile viewports only -->
    <nav class="mobilenav">
        @{
            if (parent != null) {
                <[email protected](ulClass)>
                    @foreach (var item in parent.Children.Where("Visible")) {
                        var selected = Array.IndexOf(Model.Path.Split(','), item.Id.ToString()) >= 0 ? " class=\"selected\"" : "";
                        <[email protected](selected)>
                            <a href="@item.Url" title="@item.Name">@item.Name</a>
                        </li>
                    }
                </ul>
            }
        }
    </nav>
    <!-- end // -->
       
    <!-- so now for each parent above that has children we need to create a nav block for each parent. -->
    <!-- the nav block needs to show all levels starting at level 2 onwards but show the parent as a link in the <header> tag only -->
    @{
    <nav class="subnav panel-nameofparentnode">
        <header>
            <h1><a href="#" title="">Parent Node Name</a></h1>
        </header>
    <ul>
    <li>
    <a href="#" title="">Level 2 child</a>
    <ul>
    <li><a href="#" title="">Level 3 child</a></li>
    <li><a href="#" title="">etc...</a></li>
    </ul>
    </li>
    </ul>
    <div class="clearfix"><!--//--></div>
    </nav>
    }
    <!-- end // -->

    So where I'm kinda stuck here is the sub-nav to the parent menu above. Each parent menu that has children will need to have it's own <nav> block that will contain its own children so I assume I need to loop through the parents and if children are present create a <nav class="subnav panel-nameofparent">...</nav>, then within this I need to write out a nested UL/LI structure for all child nodes from 2nd level onwards.

    What do you think might work in this instance?

    Many thanks,
    Mike

  • Mike 62 posts 274 karma points
    Jul 15, 2013 @ 18:43
    Mike
    0

    So for the sub navigation block I've put together this so far:

    @{
        if (Model.Children.Where("Visible").Count() > 0) {
            foreach (var childPage in Model.Children.Where("Visible")) {
                <nav class="subnav [email protected]().Replace(" ", "")">
                    <header>
                        <h1><a href="@childPage.Url" title="@childPage.Name Overview">@childPage.Name Overview</a></h1>
                    </header>

                    @if (childPage.Children.Where("Visible").Any()) {                   
                        @* Call our helper to display the children *@
                        @childPages(childPage.Children)
                    }
                    <div class="clearfix"><!--//--></div>
                </nav>
            }
        }
    }

    @helper childPages(dynamic pages) {
        @* Ensure that we have a collection of pages *@
        if (pages.Any())
        {
            <ul>
                @foreach (var page in pages.Where("Visible"))
                {
                    <li>
                        <a href="@page.Url">@page.Name</a>
                       
                        @* if the current page has any children, where the property umbracoNaviHide is not True *@
                        @if (page.Children.Where("Visible").Any())
                        {                       
                            @* Call our helper to display the children *@
                            @childPages(page.Children)
                        }
                    </li>
                }
            </ul>
        }
    }

    The main and obvious issue here is that this script works great on the homepage but once you've navigated away from this the sub nav block no longer works. I'm sure that this is because the script is rendering from the homepage node only so I need to work out how to render the sub-nav from the top of the node structure at all times regardless of the page the user is on.

    Can anyone tell me where I'm going wrong here?

    Many thanks,
    Mike

  • Mike 62 posts 274 karma points
    Jul 15, 2013 @ 19:24
    Mike
    100

    Simple fix - I changed:

    @{
       
    if(Model.Children.Where("Visible").Count()>0){
           
    foreach(var childPage inModel.Children.Where("Visible")){
               
    <nav class="subnav [email protected]().Replace("", "")">
                   
    <header>
                       
    <h1><a href="@childPage.Url" title="@childPage.Name Overview">@childPage.NameOverview</a></h1>
                   
    </header>

                    @if (childPage.Children.Where("Visible").Any()) {                    
                        @* Call our helper to display the children *@
                        @childPages(childPage.Children)
                    }
                    <div class="clearfix"><!--/
    /--></div>
               
    </nav>
            }
        }
    }

    to:

    @{
        foreach (var childPage in parent.Children.Where("Visible")) {
            <nav class="subnav [email protected]().Replace(" ", "")">
                <header>
                    <h1><a href="@childPage.Url" title="@childPage.Name Overview">@childPage.Name Overview</a></h1>
                </header>
                @if (childPage.Children.Where("Visible").Any()) {                   
                       @* Call our helper to display the children *@
                       @childPages(childPage.Children)
                }
                <div class="clearfix"><!--//--></div>
            </nav>
        } 
    }
Please Sign in or register to post replies

Write your reply to:

Draft