Orchard 1.4.2 - LocalNav - can't get tabs to display

Topics: Customizing Orchard, Writing modules
Jul 17, 2012 at 12:12 PM

Setup:

I am writing a module (CorporateEmails) that has it's own piece of AdminMenu. The List menu item (see AdminMenu.cs below) displays a list of corporate emails.  One column of the list displays a link ("Manage") that takes the user through to what I would like to be a tabbed interface, with three tabs (Edit, Delete, Messages).  Clicking on the "Manage" link effectively takes you to the Edit tab...  although, with my AdminMenu.cs code, no tabs are showing....

AdminMenu.cs

using Orchard.UI.Navigation;
 
namespace Wingspan.CorporateEmails {
    public class AdminMenu : INavigationProvider
    {
        private readonly Work<RequestContext> _requestContextAccessor;
 
        public string MenuName
        {
            get { return "admin"; }
        }
 
        public AdminMenu(Work<RequestContext> requestContextAccessor) {
            _requestContextAccessor = requestContextAccessor;
            T = NullLocalizer.Instance;
        }
 
        private Localizer T { getset; }
 
        public void GetNavigation(NavigationBuilder builder)
        {
            var requestContext = _requestContextAccessor.Value;
            var aliasValue = (string)requestContext.RouteData.Values["alias"];
            var al = string.Empty;
 
            if (!string.IsNullOrEmpty(aliasValue)) al = aliasValue;
            
            builder.Add(menu => menu
                    .Caption(T("Corporate Emails"))
                    .Position("2")
                    .LinkToFirstChild(false)
 
                    .Add(submenu => submenu
                        .Caption(T("List"))
                        .Position("2.1")
                        .Action("Index""EmailAddressesAdmin"new { area = "Wingspan.CorporateEmails" })
                            .Add(T("Edit"), "0",  i => i.Action("Edit""EmailAdressesAdmin"new { area = "Wingspan.CorporateEmails", alias = al }).LocalNav())
                            .Add(T("Delete"), "1", i => i.Action("Delete""EmailAdressesAdmin"new { area = "Wingspan.CorporateEmails", alias = al }).LocalNav())
                            .Add(T("Messages"), "2", i => i.Action("ListMessages""EmailAdressesAdmin"new { area = "Wingspan.CorporateEmails", alias = al }).LocalNav())
                    )
                );
        }
    }
}

I presume I am doing something wrong, but can't see what.  

Is this the right way to do what I want?

PS:  I can show the Route.cs if you need to see that.  However, all routes work fine, if entered manually.


Jul 17, 2012 at 8:37 PM

Any suggestions?  Still can't see what I am doing wrong.

Coordinator
Jul 17, 2012 at 11:01 PM

Compare closely with other similar menus is all I can recommend. Can't see an obvious mistake.

Jul 18, 2012 at 9:12 AM
Edited Jul 18, 2012 at 12:18 PM

[Edited]

See below.  I used David Hayden's Calendar example to inspect the issue with a clean module to see what works.

Jul 18, 2012 at 10:15 AM
Edited Jul 18, 2012 at 12:18 PM

Using David Hayden's Calendar example, I have created a new module, added an AdminController and AdminMenu.cs.

It works.

I have then adapted the example to match the situation I want to achieve, ie, clicking on the Admin Menu item, eg, Calendar, takes you to a Calendar.  The Calendar just has a link to Month.  I click on month, and the LocalNav tabs display correctly.

I am now adding a routes.cs class to set up routes, and will build up my calendar module as with my Corporate Emails module until I hit a negative result with the LocalNav tabs.

Jul 18, 2012 at 11:37 AM
Edited Jul 18, 2012 at 12:18 PM

Still with my Wingspan.Calendar test module.

I found one issue caused by including the parameter in my route definition and giving it a UrlParameter.Optional when it wasn't optional.  The issues this produced included the tabs not displaying, but not always.

I have removed all such snow-blind bugs from my Wingspan.CorporateEmails module, but the tabs still not displaying.  However will look at the routes really carefully.

Jul 18, 2012 at 12:13 PM
Edited Jul 18, 2012 at 1:04 PM

I have simplified my routes, but still no joy with the LocalNav tabs.  Can anyone have a look at these routes, please, and see if you spot a problem?

new RouteDescriptor
                {
                    Route = new Route(
                                "corporate-emails/sent-to/{alias}",
                                new RouteValueDictionary
                                {
                                    {"area""Wingspan.CorporateEmails"},
                                    {"controller""EmailAddressesAdmin"},
                                    {"action""ListMessages"}
                                }, 
                                new RouteValueDictionary(), 
                                new RouteValueDictionary
                                {
                                    {"area""Wingspan.CorporateEmails"}
                                }, 
                                new MvcRouteHandler())
                },
                new RouteDescriptor
                {
                    Route = new Route(
                                "corporate-email/{alias}/{action}",
                                new RouteValueDictionary
                                {
                                    {"area""Wingspan.CorporateEmails"},
                                    {"controller""EmailAddressesAdmin"}
                                }, 
                                new RouteValueDictionary(), 
                                new RouteValueDictionary
                                {
                                    {"area""Wingspan.CorporateEmails"}
                                }, 
                                new MvcRouteHandler())
                }

The routes are called from the Index view as follows:

 <div>&nbsp;
                    <a href="@Url.Action("ListMessages""EmailAddressesAdmin"new {alias = ce.Alias})" title="@T("Messages")">@T("Messages")</a>@T(" | ")
                    <a href="@Url.Action("Edit""EmailAddressesAdmin"new { alias = ce.Alias })" title="@T("Edit")">@T("Edit")</a>@T(" | ")
                    <a href="@Url.Action("Delete""EmailAddressesAdmin"new {alias = ce.Alias})">@T("Delete")</a>
                    
                </div>
Coordinator
Jul 23, 2012 at 1:10 PM

The name of the module (not feature) is Wingspan.CorporateEmails, right? Do the routes work?

Jul 23, 2012 at 10:40 PM

The name of the module AND the feature is Wingspan.CorporateEmails.

The routes work.

What do you think is missing?  Or wrong?

Coordinator
Jul 24, 2012 at 12:57 AM

Just checking: you asked that we check your routes so I thought something was wrong with them, but now you say that they work. What we should probably check instead is the current state of your menu.cs.

Jul 24, 2012 at 8:08 AM

My AdminMenu.cs file is as follows:

using System.Web.Routing;
using Orchard.Environment;
using Orchard.Localization;
using Orchard.UI.Navigation;
 
namespace Wingspan.CorporateEmails {
    public class AdminMenu : INavigationProvider
    {
        private readonly Work<RequestContext> _requestContextAccessor;
 
        public string MenuName
        {
            get { return "admin"; }
        }
 
        public AdminMenu(Work<RequestContext> requestContextAccessor) {
            _requestContextAccessor = requestContextAccessor;
            T = NullLocalizer.Instance;
        }
 
        private Localizer T { getset; }
 
        public void GetNavigation(NavigationBuilder builder)
        {
            var requestContext = _requestContextAccessor.Value;
            var aliasValue = (string)requestContext.RouteData.Values["alias"];
            var al = string.Empty;
 
            if (!string.IsNullOrEmpty(aliasValue)) al = aliasValue;
 
            builder.Add(menu => menu
                .Caption(T("Corporate Emails"))
                .Position("2")
                    .Action("Index""EmailAddressesAdmin"new { area = "Wingspan.CorporateEmails" })
                        .Add(T("Edit"), "0", i => i.Action("Edit""EmailAdressesAdmin"new { area = "Wingspan.CorporateEmails", alias = al }).LocalNav())
                        .Add(T("Delete"), "1", i => i.Action("Delete""EmailAdressesAdmin"new { area = "Wingspan.CorporateEmails", alias = al }).LocalNav())
                        .Add(T("Messages"), "2", i => i.Action("ListMessages""EmailAdressesAdmin"new { area = "Wingspan.CorporateEmails", alias = al }).LocalNav())
            );
        }
    }
}
Coordinator
Jul 24, 2012 at 1:13 PM

And does *anything* appear or is it just the tabs that don't appear? Please provide as much detail as possible.

Jul 24, 2012 at 5:21 PM

It is just the tabs that don't appear.  Everything else works just fine.

I have checked with Inspect Element (Chrome) and it shows the empty tab menu.

My Wingspan.Calendar test module works fine, so there must be some silly error somewhere that is preventing the tabs displaying.

I have circumvented the problem by creating my own 'tabs'.

If I have the problem with another module (or not) that might provide some insight into what I am doing wrong.

Thanks your help.

Coordinator
Jul 24, 2012 at 5:48 PM

You're saying that there is markup being rendered for the tabs? Can you copy it here?

Jul 24, 2012 at 9:10 PM

Bertrand

This is the markup I am referring to - the ul tag has nothing in it:

<div id="local-navigation">                <div class="zone zone-local-navigation"><ul class="localmenu localmenu-local-admin" role="local-navigation"></ul></div>            </div>

Coordinator
Jul 26, 2012 at 2:42 PM

The empty string set to al seems a little weird, and I wouldn't be surprised if it messed up the route, which doesn't have a default value for alias. Can you experiment with setting something else than empty string there, just to check?

Jul 26, 2012 at 3:33 PM

I have tried setting al to a possible value, eg, "andrew".

I have also tried giving the alias parameter a default value ("andrew" or UrlParameter.Optional).

Nothing works.

The same structure in my test Wingspan.Calendar works fine.  It has a string variable m that is also set to string.Empty and it works fine.

So the problem is elsewhere, but I am blowed if I can find it.

I am happy to post the module to you (Or on the Gallery) for you to look at if you want.  It works really well, only it just doesn't have that extra bit of UI that the localnav would give it.

To be honest, I have given up for now.  I need to get on with other jobs and like I say, the functionality is there and packaged in a module, so dead easy to re deploy in a different app.

Some one day I will have a Eureka moment and will crack it, but in the mean time I can live with it.

Many thanks for trying so hard.

Andrew

Coordinator
Jul 26, 2012 at 4:51 PM

I'm as puzzled as you are. I have a module that adds a tab to an existing menu item, if that helps in any way. Here is my code.

using Orchard.Environment.Extensions;
using Orchard.Localization;
using Orchard.UI.Navigation;

namespace Vandelay.Industries.Menus {
    [OrchardFeature("Vandelay.ThemePicker")]
    public class ThemePickerAdminMenu : INavigationProvider {
        public Localizer T { get; set; }
        public string MenuName { get { return "admin"; } }

        public void GetNavigation(NavigationBuilder builder) {
            builder.AddImageSet("themes")
                .Add(
                    T("Themes"), "10",
                    menu => menu.Action("Index", "Admin", new {area = "Orchard.Themes"})
                                .Permission(Orchard.Themes.Permissions.ApplyTheme)
                                .Add(
                                    T("Picker"), "4",
                                    item => item.Action("Index", "Admin", new {area = "Vandelay.Industries"})
                                                .Permission(Orchard.Themes.Permissions.ApplyTheme).LocalNav()));
        }
    }
}