8

Resolved

CustomLink menu items not assigned 'current' class

description

This issue is related to changes made to the core MenuItem.cshtml view as part of the changes for the new ShapeMenuItem.

http://orchard.codeplex.com/SourceControl/changeset/555a6fd44ba0

The "current" css class is now based on the value of Model.Selected (previously this was set by comparing the requested url with the menuitem model url directly in the view).

This works fine for ContentItem menu items (and looks much cleaner), however when I build up a multi-depth hierarchy of CustomLink menu items, the "current" class is not being added to those items when they are selected (neither the selected items or any parent items that happen to also be CustomLink menu items).

Model.Selected (MenuItem.Selected) is set by the call to SetSelectedPath() in Framework\UI\Navigation\NavigationHelper.cs and inside the SetSelectedPath() routine it is comparing the RouteValues of each MenuItem to the current route information.

The problem is that (for whatever reason) MenuItem.RouteValues is null for CustomLink menu items.

I'm thinking the fix will either involve investigating why CustomLink menu items do not have their RouteValues property set, or alternatively the SetSelectePath() method in NavigationHelpers.cs could possibly make a call to try to resolve the route information for a menu item (from the Href or Url property) in the case where its RouteValues property is null?

comments

mjy78 wrote Mar 5, 2013 at 12:14 PM

Furthermore to this, it would seem that breadcrumb menu widgets aren't working with CustomLink menu items either (presumably for the same reason).

Piedone wrote Mar 5, 2013 at 5:29 PM

Good description. I noticed the symptom that breadcrumbs are not working with custom links.

dsendelb wrote Apr 12, 2013 at 1:22 AM

I actually ran into this issue when I was working on a menu highlighting module for Orchard and fixed it.

Basically I overrode the Menu Widget Part driver and injected a custom service to highlight the active path.

In that service I used the SetSelectedPath() method in NavigationHelper.cs, but if it returned null I used my custom "highlighttrail" method to set the path based on URL.

If anyone is interested the code for that can be found inside MenuItemService.cs in the code below:
https://orchardnav.codeplex.com/

Thanks

jao28 wrote Apr 17, 2013 at 4:54 PM

Hello everyone,

This solution might look a little dumb but it makes breadcrumbs work by getting the RouteData for the current page and assigning that to the Custom Link if the Custom Link is for the current page (since for some reason Orchard isn't populating the RouteData for Custom Links). Personally, the better solution is to find out where Orchard does it's magic and put this logic there (I just don't know where that is). Here is my code/hack which gets put in "MenuWidgetPartDriver":
// This is existing line of code - around line 61
IEnumerable<MenuItem> menuItems = _navigationManager.BuildMenu(menu);

// EMS CHANGE - start
// Trying to get routevalues where from the href
menuItems = TryGetRouteValues(menuItems);
// EMS CHANGE - end
And here are the two methods which accomplish the assigning of the Route Values:
// ADDED BY EMS - start
private IEnumerable<MenuItem> TryGetRouteValues(IEnumerable<MenuItem> menuItems) {
    foreach (var menuItem in menuItems) {
        if (menuItem.RouteValues == null) {
            if (!String.IsNullOrEmpty(menuItem.Href)) {
                menuItem.RouteValues = TryGetRouteValuesFromHref(menuItem.Href);
            }
        }
        menuItem.Items = TryGetRouteValues(menuItem.Items);
    }
    return menuItems;
}

private RouteValueDictionary TryGetRouteValuesFromHref(string href) {
    RouteValueDictionary result = null;

    // Since GetRouteData (which is what Alias overrides) only accepts httpcontext, get context with passed in url
    //  The only way I can see this working is by using the current url context and see if it equals the href, should fix breadcrumb
    var httpContext = _workContextAccessor.GetContext().HttpContext;

    if (httpContext.Request.Path == href) {
        RouteData routeData = httpContext.Request.RequestContext.RouteData;
        if (routeData != null) {
            result = new RouteValueDictionary(routeData.Values);
        }
    }

    return result;
}
// ADDED BY EMS - end
I realize this is a hack and there is likely a better place to have the RouteValues but it meets my needs right now and maybe someone else's.

rupertwhitlock wrote May 7, 2013 at 2:55 PM

Yes, CustomLink menu items do not work at all as breadcrumbs.

I have a menu which includes a custom link "~/latest-news". When I browse to a blog post at "~/latest-news/my-blog-post" I expect to see the breadcrumb "Home > Latest News", but as the RouteValues for the CustomLink are null, this does not work.

I have tried the two hacks above. I have had no luck as they only work if the current URL exactly matches the URL of the CustomLink.

Stanton_R wrote May 10, 2013 at 8:18 AM

Any progress on this as My menu items where I use custom links do not have current state set and my styles no longer change the look of the current / selected menu state.

sebastienros wrote May 20, 2013 at 8:43 PM

Fixed in changeset a3d7732104b3

sfmskywalker wrote Mar 28 at 12:28 AM

Fixed in changeset d9e63b0e38bfd7ac6f010dbc065331d205791a01