Search code examples
c#html.netrazorumbraco

Stop the navigation bar from refreshing - Umbraco


I couldn't find anything regarding my issue so I decided to post one myself.

I am using a navigation bar that has dropdown menu's. Whenever I open the dropdown and navigate to one of those pages, the navigation refreshes and closes the dropdown menu. The dropdown menu needs to stay open when I go over to one of the pages, I tried Model.Content.AncestorOrSelf().Descendants("document") to try and keep the navigation bar from refreshing but that doesn't seem to work (as people said).

Here's my menu structure:

menu

Everything underneath "Hulp per browser" is in a dropdown and will disappear when I click on "Hulp per browser" again.

Here is my code:

@inherits Umbraco.Web.Mvc.UmbracoTemplatePage
<div class="col-sm-3">
    <div class="NavDigiCampuz">
        <h3>Helpcentrum</h3>
        <li class="NoBullet"><a class="NormalA" href="https://digicampuz.nl/">Terug naar digicampuz</a></li><br>
            <ul class="nav nav-list tree">
                @{                                  
                    var documentRootNodeId = Model.Content.GetPropertyValue("documentRoot", true); // Fetch recursive document root id.
                    var selection = Umbraco.TypedContent(documentRootNodeId).Children.Where("Visible"); // Select all nodes below the document root.
                }

                @foreach(var item in Model.Content.AncestorOrSelf(2).Descendants("document").ToList()){
                    foreach (var ItemChild in @item.Children("categorieMenu")){
                        if(ItemChild.Children.Any())
                        {
                        <li class="MenuItems"><p>@ItemChild.Name</p></li>   
                            foreach (var Subitem in @ItemChild.Children){
                                if (Subitem.Children("hoofdstuk").Any())
                                {
                                    <li class="item">
                                        @if(Subitem.GetPropertyValue("hoofdstukIcoon") != "") {
                                            <a class="NormalA aNav" href="#"><i class="fa fa-@(Subitem.GetPropertyValue("hoofdstukIcoon")) fa-fw"></i> @Subitem.Name <i id="Arrow" class="fa fa-arrow-right" style="font-size:10px;" aria-hidden="true"></i></a>
                                        }else{
                                            <a class="NormalA aNav" href="#">@Subitem.Name <i id ="Arrow" class="fa fa-arrow-right" style="font-size:10px;" aria-hidden="true"></i></a>
                                        }
                                        @foreach (var Finalitem in @Subitem.Children){
                                        <ul class="submenu">
                                            @if(Finalitem.GetPropertyValue("hoofdstukIcoon") != "") {
                                            <br><li><a class="NormalA aNav" href="@Finalitem.Url"><i class="fa fa-@(Finalitem.GetPropertyValue("hoofdstukIcoon")) fa-fw"></i>@Finalitem.Name </a></li>  
                                            }else{
                                                <br><li><a class="NormalA aNav" href="@Finalitem.Url">@Finalitem.Name</a></li><br>
                                            }
                                        </ul>   
                                        } 
                                    </li>
                                    }else
                                        {
                                            if(Subitem.GetPropertyValue("hoofdstukIcoon") != "") {
                                                <li><a class="NormalA aNav" href="@Subitem.Url"><i class="fa fa-@(Subitem.GetPropertyValue("hoofdstukIcoon")) fa-fw"></i> @Subitem.Name</a></li>
                                            }else{
                                                <li><a class="NormalA aNav" href="@Subitem.Url">@Subitem.Name</a></li>  
                                            }
                                    }
                                }   
                            }
                        }
                    }   
            </ul>
    </div>
</div>

<script>
    $(".item").click(function(){
        $(this).children(".submenu").toggle(); //it will display or hide your submenu when clicking the item.
    });
</script>

<style>
    .submenu{
    display: none;
    list-style:none;
    }
</style>    

I do plan on removing the script and style from the page when everything works.


Solution

  • First thing you have several issues in the code:

    • Remove the Where to filter Children and keep it like var selection = Umbraco.TypedContent(documentRootNodeId).Children("Visible");
    • Cast your hoofdstukIcoon to string Subitem.GetPropertyValue<string>("hoofdstukIcoon")
    • The first <li class="noBullet"> should be in your nav-list, not outside.
    • You shouldn't put <br> between your list items, if you want margins use css.

    Now we'll focus on your issue with the submenus. What you are doing with your javascript is just using the display property to hide or show your submenu but when the page is rendered, Razor has no idea if that should be hidden or not. To solve this you have to create a new class like .visible that can be used by Razor and Javascript.

    Yous hould also move your <ul class="submenu"> out of your @foreach (var Finalitem in Subitem.Children) because what you are doing now is creating a new list with one item for each one.

    You should also include a conditional before your submenu in case there a no children and we don't want submenu @if (Subitem.Children.Any()) {

    The way of telling your submenu with Razor if it has to diplay or not is doing this:

    var isVisible = Model.Content.IsDescendantOrSelf(Subitem) ? "visible" : "";
    <ul class="submenu @isVisible">
    

    So in that example your submenu will show if the current page is this Subitem or one of its children.

    And your JS script would become this:

    $(".item").click(function () {
            $(this).children(".submenu").toggleClass('visible'); //it will display or hide your submenu when clicking the item.
    });
    

    And your CSS this:

    <style>
        .submenu {
            display: none;
            list-style: none;
        }
    
        .submenu.visible {
            display: block;
        }
    </style>