Copied to clipboard

Flag this post as spam?

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


  • Matt 315 posts 737 karma points
    Dec 04, 2019 @ 09:13
    Matt
    0

    Hi,

    I'm trying to create a dynamic navigtaion menu as MegaNav isnt here for Umbraco8 yet.

    I've got the following code which works fine for a single menu with no drop downs.

    @inherits Umbraco.Web.Mvc.UmbracoViewPage
    
    
    
    <div data-collapse="medium" data-animation="default" data-duration="400" class="navbar w-nav">
    <div class="w-container">
    <nav role="navigation" class="navmenu w-nav-menu">
        <a href="/" class="navlink w-nav-link">Home</a>
    @{
        var selection = Umbraco.ContentAtRoot().FirstOrDefault()
        .Children()
        .Where(x => x.IsVisible());
    }
    
        @foreach (var item in selection)
        {
        <a href="@item.Url" class="navlink w-nav-link">@item.Name</a>
        }
    </nav>
            <div class="handburger w-nav-button">
              <div class="w-icon-nav-menu"></div>
            </div>
     </div>
    </div>
    

    However, I want to add some dropdowns to the menus for nodes with children using the following html code;

          <div data-hover="1" data-delay="0" class="w-dropdown">
            <div class="navlink w-dropdown-toggle">
              <div>What we do</div>
            </div>
            <nav class="w-dropdown-list"><a href="#" class="navlink w-dropdown-link">Drop Down link 1</a><a href="#" class="navlink w-dropdown-link">rop Down link 2</a><a href="#" class="navlink w-dropdown-link">rop Down link 3</a></nav>
          </div>
    

    Would anyone be able to help how I can add this to my code?

    Thanks

  • Kieron 152 posts 390 karma points
    Dec 04, 2019 @ 14:07
    Kieron
    0

    Something like this any good?

     @foreach (var item in selection)
                {
                    if (item.Children().Count() == 0) {
                        <a href="@item.Url" class="navlink w-nav-link">@item.Name</a>
                    }
                    else if (item.Children().Count() >= 1) {
                        <div data-hover="1" data-delay="0" class="w-dropdown">
                        <div class="navlink w-dropdown-toggle">
                            <div>@item.Name</div>
                        </div>
                            @foreach (var child in item.Children().Where(c => c.IsVisible())) { 
                                <nav class="w-dropdown-list">
                                    <a href="@child.Url" class="navlink w-dropdown-link">@child.Name</a>
                                </nav>
                            }
                        </div>
                    }
                }
    

    Maybe it would be more efficient to do

    If children {
          // children
    }
    else {
          //no children link
    }
    
  • Jeffrey Veer 31 posts 267 karma points
    Dec 04, 2019 @ 14:59
    Jeffrey Veer
    101

    Just to add on to the reply of Kieron, keep in mind that the suggested code contains a common pitfall (over-querying). A solution that solves this issue would be something like:

    @foreach (var item in selection)
    {
        var children = item.Children(c => c.IsVisible()).ToArray();
        if (children.Any())
        {
            <div data-hover="1" data-delay="0" class="w-dropdown">
                <div class="navlink w-dropdown-toggle">
                    <div>@item.Name</div>
                </div>
                @foreach (var child in children)
                {
                    <nav class="w-dropdown-list">
                        <a href="@child.Url" class="navlink w-dropdown-link">@child.Name</a>
                    </nav>
                }
            </div>
        }
        else
        {
            <a href="@item.Url" class="navlink w-nav-link">@item.Name</a>
        }
    }
    
  • Kieron 152 posts 390 karma points
    Dec 04, 2019 @ 15:03
    Kieron
    1

    Yeah that looks much nicer. :)

  • Matt 315 posts 737 karma points
    Dec 04, 2019 @ 15:41
    Matt
    0

    Thanks thats great and worked a treat!

    My only issue is it only shows 1 node in the drop down lists at a time? if I create more then 1 child under a node it will only show the latest 1?

    Thanks

  • Jeffrey Veer 31 posts 267 karma points
    Dec 04, 2019 @ 15:44
    Jeffrey Veer
    0

    Hi Matt,

    Glad it worked! Can you share the code you currently have? I think it should work with the code above, but I might be missing something!

    Let me know and I will try to help you further :)

  • Matt 315 posts 737 karma points
    Dec 04, 2019 @ 15:45
    Matt
    0

    Thanks my code is below

    @inherits Umbraco.Web.Mvc.UmbracoViewPage
    
    @{
        var selection = Umbraco.ContentAtRoot().FirstOrDefault()
        .Children()
        .Where(x => x.IsVisible());
    }
    
    <div data-collapse="medium" data-animation="default" data-duration="400" class="navbar w-nav">
    <div class="w-container">
    <nav role="navigation" class="navmenu w-nav-menu">
        <a href="/" class="navlink w-nav-link">Home</a>
    @foreach (var item in selection)
    {
        var children = item.Children(c => c.IsVisible()).ToArray();
        if (children.Any())
        {
            <div data-hover="1" data-delay="0" class="w-dropdown">
                <div class="navlink w-dropdown-toggle">
                    <div>@item.Name</div>
                </div>
                @foreach (var child in children)
                {
                    <nav class="w-dropdown-list">
                        <a href="@child.Url" class="navlink w-dropdown-link">@child.Name</a>
                    </nav>
                }
            </div>
        }
        else
        {
            <a href="@item.Url" class="navlink w-nav-link">@item.Name</a>
        }
    }
         </nav>
            <div class="handburger w-nav-button">
              <div class="w-icon-nav-menu"></div>
            </div>
     </div>
    </div> 
    
  • Jeffrey Veer 31 posts 267 karma points
    Dec 04, 2019 @ 15:50
    Jeffrey Veer
    0

    Hmm, and it's only rendering the latest added child-page to the sub nodes of the pages under the root?

    A wild guess is that you have the umbracoNaviHide set to true? (IsVisible() filters those out)

    Another option might be that it is hidden by some CSS or JavaScript on the front-end? You might want to check the source code on your page, just to be entirely sure :)

  • Matt 315 posts 737 karma points
    Dec 04, 2019 @ 15:55
    Matt
    0

    Yeap thats correct, if I create a new child under node "what we do" it would then hide the previous child created.

    I did think of the NaviHide, checked those and even tried removing the IsVisible statement but still the same issue.

    Hmm I'll try check the CSS/JS but cant see it being an issue as works out of Umbraco, strange.

  • Matt 315 posts 737 karma points
    Dec 04, 2019 @ 16:25
    Matt
    1

    Got it working, I had to take the following class outside of my loop;

        <nav class="w-dropdown-list">
    
    </nav>
    

    Thanks :)

  • kalgi kansara 18 posts 108 karma points
    Sep 21, 2021 @ 10:03
    kalgi kansara
    0

    Hi !! This solution worked for me

    In master.cshtml

    @{
    var rootNodes = Umbraco.TypedContentAtRoot().ToList();
    Layout = null;
    }

    Inside nav tag

        <ul>
            @foreach (var node in rootNodes)
            {
            <div class="dropdown">                   
                <a class="dropbtn" style="padding-right:20px;color:white" href="@node.Url">@node.Name</a>
    
                <div class="dropdown-content">
    
                    @foreach (var c in node.Children)
                    {
                        <a href="@c.Url" class="nav-link w-nav-link">@c.Name</a>
                    }
                </div>
            </div>
            }
        </ul>
    

    In Master.css

    .dropdown-content a:hover {
    background-color: #ddd;
    }
    
    .dropdown:hover .dropdown-content {
    display: block;
    }
    
    .dropdown:hover .dropbtn {
    background-color: maroon;
    }
    
    .dropdown {
    position: relative;
    display: inline-block;
    }
    
    .dropdown-content {
    display: none;
    position: absolute;
    background-color: #f1f1f1;
    min-width: 160px;
    box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
    z-index: 1;
    }
    
    .dropdown-content a {
     color: black;
     padding: 12px 16px;
     text-decoration: none;
     display: block;
    }
    
Please Sign in or register to post replies

Write your reply to:

Draft