Copied to clipboard

Flag this post as spam?

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


  • Morten 105 posts 345 karma points
    Apr 20, 2017 @ 09:36
    Morten
    0

    Nested/dropdown menu - Dynamically "generated" from Umbraco backend?

    Heya! I am trying to populate my header with links. I have two dropdowns at the moment. I would like to populate the links using Umbraco and Razor, so nothing is hardcoded. This can be done quite easily (see code below), but populating the dropdowns is the tricky part.

    I'm not sure how I would populate the dropdown in a good way. They are not subpages or anything like that, but they are simply dropdowns to make the header less wide. Here's how I populate my header using Razor by grabbing the links in Umbraco:

    var home = CurrentPage.Site();
    
    @foreach (var item in home.Children.Where("Visible"))
    {
        <li class="@(item.IsAncestorOrSelf(CurrentPage) ? "active" : null)">
            <a href="@item.Url" class="nav-link">@Umbraco.GetDictionaryValue(item.Name)</a>
        </li>
    }
    

    home.Children.Where("Visible") is simply grabbing all the child pages, where I have not checked the umbracoNaviHide.

    This is currently how my header is created NOT using Umbraco (which I need to populate using the pages from Umbraco):

    <nav class="navbar navbar-toggleable-lg navbar-light fixed-top">
      <div class="d-flex align-items-center justify-content-between">
        <button class="navbar-toggler navbar-toggler-left" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
          <span class="navbar-toggler-icon"></span>
        </button>
        <a class="navbar-brand ml-3" href="/en">
          <img src="logo.png" class="logo" alt="logo">
        </a>
      </div>
      <div class="collapse navbar-collapse" id="navbarSupportedContent">
        <ul class="navbar-nav mr-auto justify-content-between full-width">
          <li class="nav-item dropdown">
            <a class="nav-link dropdown-toggle" href id="navbarDropdownMenuLink" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
              About
            </a>
            <div class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
              <a class="dropdown-item" href="#">About Us</a>
              <a class="dropdown-item" href="#">History</a>
            </div>
          </li>
          <li>
            <a href="" class="nav-link">Our Products</a>
          </li>
          <li class="nav-item dropdown">
            <a class="nav-link dropdown-toggle" href id="navbarDropdownMenuLink2" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
              Resources
            </a>
            <div class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink2">
              <a class="dropdown-item" href="#">Tips</a>
              <a class="dropdown-item" href="#">News</a>
            </div>
          </li>
          <li>
            <a href="" class="nav-link">Contact Us</a>
          </li>
        </ul>
      </div>
    </nav>
    

    This will produce a result like this: https://codepen.io/anon/pen/QvyeRm

    I don't want any of the links to be affected by this, as the links or pages doesn't really have anything to do with the header's layout. Here are some example URLs:

    /en/about-us/
    /en/history/
    /en/our-products/
    /en/tips/
    

    I hope that makes sense.

    Is there a good and easy way to do this? Thanks!

  • Morten 105 posts 345 karma points
    Apr 27, 2017 @ 07:20
    Morten
    0

    Sorry for bumping this, but I need to know if this is possible.

  • Alan Thom 3 posts 76 karma points c-trib
    Apr 27, 2017 @ 08:34
    Alan Thom
    0

    Hi Morten

    You'll want to loop over the visible nodes beneath your homepage, then for each of these loop over any visible children it may have. You should end up with something similar to this:

    @{
    var root = Umbraco.TypedContentAtRoot().FirstOrDefault();
    
    <ul class="navbar-nav mr-auto justify-content-between full-width">
        @foreach (var firstLevel in root.Children.Where(x => x.IsVisible()))
        {
            <li class="nav-item dropdown">
                <a class="nav-link dropdown-toggle" href="@firstLevel.Url" id="navbarDropdownMenuLink" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
                    @firstLevel.Name
                </a>
                @if (firstLevel.Children.Any(x => x.IsVisible()))
                {
                    <div class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
                        @foreach (var secondLevel in firstLevel.Children.Where(x => x.IsVisible()))
                        {
                            <a class="dropdown-item" href="@secondLevel.Url">@secondLevel.Name</a>
                        }
                    </div>
                }
    
            </li>
        }
    </ul>
    

    }

  • Morten 105 posts 345 karma points
    Apr 27, 2017 @ 11:52
    Morten
    0

    Where would I specify which items I want in the dropdown though? I want the exact result I showed in the Codepen above, but dynamically generated through the nodes from Umbraco. This does not do that and it cannot be done in the Razor code alone.

  • Nik 1593 posts 7151 karma points MVP 6x c-trib
    Apr 27, 2017 @ 09:17
    Nik
    0

    Hi Morten,

    There is a new plugin out relatively recently called MegaNav. This allows you to build a navigation as a property on a page customising where things sit, their order, their level etc.

    I would start by looking at that if your navigation is not related to your site structure in the back office :-)

    Nik

  • Morten 105 posts 345 karma points
    Apr 27, 2017 @ 09:33
    Morten
    0

    Hi, Nik! That's an awesome plugin, as it looks. However, I cannot create the nested links like I want. I'm not sure how to achieve this:

    (the nested part). As I said, my pages do not have parents or anything like that. It's simply made into dropdowns because it needs to fill out less.

  • Bhawna Jain 16 posts 96 karma points
    Apr 28, 2017 @ 03:41
    Bhawna Jain
    1

    hi everybody,

    i m new to this forum.been a passive member for 4 months now. but Mortem,given code worked for me..you can try as well ,its for level 2 menu(sub menu)

    var selection = CurrentPage.Site().Children; 
    var home = Model.Content.AncestorsOrSelf(1).FirstOrDefault();
    @foreach (var item in selection) 
    {
    <li class="@(item.IsAncestorOrSelf(CurrentPage) ? " current " :null)">
        <a  href="@item.Url">@item.Name</a>
            @foreach (var childPage in @item.Children)
                {<a href=" @childPage.Url">@childPage.Name</a>
                }
        </li>   
    }
    

    replace @Umbraco.GetDictionaryValue(item.Name) in place of @item.Name..and do tell me..how it goes :)

  • Morten 105 posts 345 karma points
    May 02, 2017 @ 09:48
    Morten
    0

    Hi Bhawna

    The problem is, I do not have child pages. I have a Master page which has children but that's it.

    I need to be able to specify "THIS PAGE GOES INTO THIS DROPDOWN" and somehow specify a label for the dropdown.

    So far I have found no possible way of doing this.

  • Bhawna Jain 16 posts 96 karma points
    May 02, 2017 @ 09:56
    Bhawna Jain
    0

    Sorry Morten ,i m not able to understand it..is it like this(given screen shot)

    enter image description here

    BTW are you trying to add content into dropdown from CMS(for example content of gallery into a dropdown)?

  • Morten 105 posts 345 karma points
    May 02, 2017 @ 10:03
    Morten
    0

    I may have figured something out. I'll let you know as soon as I know if this works.

    I created a new document type called "Dropdown". The sole purpose of this is to be a parent for the dropdowns.

    Hold on.

  • Morten 105 posts 345 karma points
    May 02, 2017 @ 10:08
    Morten
    100

    Okay, I ended up doing this (which seems to work pretty well):

    @foreach (var item in selection)
    {
        if (item.GetPropertyValue<bool>("showDropdown"))
        {
            <li class="nav-item dropdown">
                <a class="nav-link dropdown-toggle" href id="navbarDropdownMenuLink" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
                    @item.GetVortoValue("Title")
                </a>
                <div class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
                    @foreach (var child in item.Children)
                    {
                        <a class="dropdown-item" href="@child.Url">@child.GetVortoValue("Title")</a>
                    }
                </div>
            </li>
        }
        else
        {
            <li>
                <a href="@item.Url" class="nav-link">@item.GetVortoValue("Title")</a>
            </li>
        }
    }
    

    I started by creating a document type called "Dropdown". The sole purpose of this document type, is to be a parent for the pages inside the dropdown. Then I set the permissions to allow the two pages I have to be inside the dropdown, and I set the permissions on my Master to allow the dropdown document type.

    Then I created a new property on the master document type, which is called "Show dropdown". If this is ticked, it will show the dropdown on the page. I had to do this, because pages with children (if(item.Children.Any())) would be true no matter what.

  • Bhawna Jain 16 posts 96 karma points
    May 02, 2017 @ 10:15
    Bhawna Jain
    0

    I m glad ,You got ur answer...though i couldn't help you much...but i think getting things done is more important than how you do it :)

  • Morten 105 posts 345 karma points
    May 02, 2017 @ 10:26
    Morten
    0

    That is absolutely correct! At least this works pretty well for me, although it's not the most elegant solution ever.

Please Sign in or register to post replies

Write your reply to:

Draft