Base solution for your next web application
Open Closed

Modifications to the Navigation Menu code #595


User avatar
0
alukaszewski created

Hi,

In my web forms based version of my application, I have centralised my navigation menu by having the code for it inside a User Control, and I reference the UC on each page. This saves greatly when adding new pages/menu items as I do not need to amend all the existing pages. I realise that ASP.NET Zero accomplishes this centralisation for me, which is a very good thing, however I wish to amend the code for the whole menu tree that gets generated.

Specifically, I wish to be able to identify LI items in the menu system by assigning them an ID=value, so that I can do something with the menu in client-side JavaScript once the page is ready. The code snippet below is what I want to be able to do...

<li class="nav-item" id="menu-parent01">
		                <a href="javascript:;">
                            <i class="icon-puzzle"></i>
                            <span class="title">Parent 01</span>
			                <span class="arrow "></span>
                        </a>
		                <ul class="sub-menu">
			                <li class="nav-item start" id="menu-parent01-child01">
				                <a href="/parent01/child01.aspx">
				                <i class="icon-grid"></i>
				                Child 01</a>
			                </li>
			                <li class="nav-item" id="menu-parent01-child02">
				                <a href="parent01/child02.aspx">
				                <i class="icon-globe"></i>
				                Child 02</a>
			                </li>
			                <li class="nav-item" id="menu-parent01-child03">
				                <a href="parent01/child03.aspx">
    			                	<i class="icon-screen-desktop"></i>
    			                	Child 03</a>
    		                	</li>

Why? In short, I am dynamically adding sub-items to the Nav-Menu using JavaScript, to represent temporary/dynamic pages that exist in my application when the user drills through into data. For instance, when they drill through a list of computer names they get a page containing details of that computer, and the Nav Menu is modified to include a sub-menu item which shows the name of the computer they are looking at.

So, where do I start? I can see that the mpaNavigationProvider.cs provides for a "customData" parameter? Is this where I might be able to add an ID when I perform the .AddItem(new MenuItemDefinition...)

Thanks,

Andy


4 Answer(s)
  • User Avatar
    0
    hikalkan created
    Support Team

    Hi,

    CustomData is a good option. Another option is to use MenuItem's Name as ID since the Name is unique in the application. But notice that name may contain "." which can be a problem for HTML's ID value. So, you can replace "." with empty string which assigning it to li tag ID.

    Thanks.

  • User Avatar
    0
    alukaszewski created

    OK, so I might be on the right track - but can I actually use the customData parameter to add an id="myid" inside the <li> tag, or is customData simply a way of adding attributes in the menu object and not a means to output something in client facing html code?

    I wish to be able to use JavaScript document.getElementById function to find an <li> in the DOM, by id, so that I can re-use my existing JavaScript code to inject a sub-item into the menu when the page has loaded. Here is my working function below;

    <script type="text/javascript">
            // Add a Dynamic Menu Item linking back to the parent page and make it active.
            var li = document.getElementById('menu-parent01-child01');
            var dynul = document.createElement('ul');
            var dynli = document.createElement('li');
            dynul.classList.add('sub-menu');
            dynli.setAttribute('id', 'menu-parent01-child01-temp01');
            dynli.classList.add('active');
            dynul.appendChild(dynli);
            li.appendChild(dynul);
    
            dynli.innerHTML = '<i class=icon-bar-chart></i>MenuName';
        </script>
    

    The function above would add a new menu item to the child01 menu item in the menu code I previously posted. or is there an alternative, more modern/MVC solution to finding the current menu item using the abp.application.navigation classes and then the page view adding in a new menu at runtime?

    Thanks for your support.

  • User Avatar
    0
    alukaszewski created

    Any idea?

  • User Avatar
    0
    hikalkan created
    Support Team

    Hi,

    I assume that you're using MPA. I'm pasting the code I wanted to say. See <span style="color:#FF0000">red</span> parts.

    @using Abp.Collections.Extensions @using MyCompanyName.AbpZeroTemplate.Web.Views @model MyCompanyName.AbpZeroTemplate.Web.Areas.Mpa.Models.Layout.SidebarViewModel @{ var calculateMenuUrl = new Func<string, string>((url) => { if (string.IsNullOrEmpty(url)) { return ApplicationPath; }

        if (UrlChecker.IsRooted(url))
        {
            return url;
        }
    
        return ApplicationPath + url;
    });
    

    } <div class="page-sidebar navbar-collapse collapse">

    &lt;ul class=&quot;page-sidebar-menu&quot; data-keep-expanded=&quot;false&quot; data-auto-scroll=&quot;true&quot; data-slide-speed=&quot;200&quot;&gt;
        @for (var i = 0; i &lt; Model.Menu.Items.Count; i++)
        {
            var menuItem = Model.Menu.Items[i];
            var isActive = Model.CurrentPageName == menuItem.Name ||
                           (!menuItem.Items.IsNullOrEmpty() &amp;&amp; menuItem.Items.Any(item =&gt; item.Name == Model.CurrentPageName));
            &lt;li &lt;span style=&quot;color:#FF0000&quot;&gt;id="@menuItem.Name.Replace(".","")"&lt;/span&gt; class="@(i==0 ? "start" : "") @(isActive ? "active" : "")">
                @if (menuItem.Items.IsNullOrEmpty())
                {
                    &lt;a href=&quot;@calculateMenuUrl(menuItem.Url)&quot;&gt;
                        &lt;i class=&quot;@menuItem.Icon&quot;&gt;&lt;/i&gt;
                        &lt;span class=&quot;title&quot;&gt;@menuItem.DisplayName&lt;/span&gt;
                    &lt;/a&gt;
                }
                else
                {
                    &lt;a href=&quot;javascript:;&quot; class=&quot;auto&quot;&gt;
                        &lt;i class=&quot;@menuItem.Icon&quot;&gt;&lt;/i&gt;
                        &lt;span class=&quot;title&quot;&gt;@menuItem.DisplayName&lt;/span&gt;
                        &lt;span class=&quot;arrow&quot;&gt;&lt;/span&gt;
                    &lt;/a&gt;
                    &lt;ul class=&quot;sub-menu&quot;&gt;
                        @foreach (var childMenuItem in menuItem.Items)
                        {
                            &lt;li &lt;span style=&quot;color:#FF0000&quot;&gt;id="@childMenuItem.Name.Replace(".", "")"&lt;/span&gt; class="@(Model.CurrentPageName == childMenuItem.Name ? "active" : "")">
                                &lt;a href=&quot;@calculateMenuUrl(childMenuItem.Url)&quot;&gt;
                                    &lt;span&gt;&lt;i class=&quot;sub-menu-icon @childMenuItem.Icon&quot;&gt;&lt;/i&gt; @childMenuItem.DisplayName&lt;/span&gt;
                                &lt;/a&gt;
                            &lt;/li&gt;
                        }
                    &lt;/ul&gt;
                }
            &lt;/li&gt;
        }
    &lt;/ul&gt;
    

    </div>

    Thus, you can easily get a menu item by it's Id. For example, to get Roles menu: $('#AdministrationRoles') Then you can add sub items if you want.