1.5.1 Nav Menus/Sub-menus

Topics: Core, Customizing Orchard, General, Writing themes
Oct 9, 2012 at 1:46 AM

First - I am a designer and am trying really hard to figure out all of the code that makes this work, but please forgive any ignorance of common sense that I convey.

Second - I've searched the discussions and can't find an answer that helps me. Close cousins, but nothing that hits the tags that I need.

So here goes...

I am currently trying to write my own Orchard theme using Bootstrap but I'm getting stuck on the menus. Because this is Bootstrap, I really want to avoid modifying the CSS. Instead, I am trying to modify views to fit Bootstrap's structural needs and class assignments.

The specific issues I am having is in the MenuItem and MenuItemLink views:

Issue #1: It looks like both the root level menu items and the sub-menu items are using the same MenuItemLink shape. When I assign a class in this view, the class is given to all menu items. Is there any easy way to define different views for the different levels? Or perhaps some If statement I could use within the view to distinguish the levels?

Issue #2: The <li> for the root level menu is located in the MenuItem view, and I have easy access to that for adding classes. But I can't find the <li> for the sub-menu items anywhere. I'm thinking that perhaps it is being created by the Html.UnorderedList helper extension. Is there any "easy" way for me to add classes the sub-menu level <li>?

Thanks in advance for any help available.

Developer
Oct 9, 2012 at 2:02 PM

Okay so MenuItems are rendered out using MenuItem.cshtml, what happens is that recursion is used, so this file would drive each level. You could create an Alternate for this file, and then add a class for each level of recursion you are at.

I can try to answer issue 2. So I have taken a look at Html.UnorderedList and it has a nice little overload for you to add classes

public static IHtmlString UnorderedList<T>(this HtmlHelper htmlHelper, IEnumerable<T> items, Func<T, int, MvcHtmlString> generateContent, string cssClass, string itemCssClass, string alternatingItemCssClass) {

Simply pass through the right values and you should be good to go.

I hope that helps a little... I am not to familier with the menu side of things.2

Nick

Oct 12, 2012 at 4:08 PM

Thanks for the reply Jetski. I'll play around with those suggestions and post back here how it all goes.

Oct 15, 2012 at 8:39 PM

So I am kinda in the same boat. Also using bootstrap, I was able to overwrite the menus to match the structure of bootstrap with Menu.cshtml and MenuItem.cshtml. But now I want to change the structure for just the footer menu. I am using designer tools and don't see any file name that would just modify the footer menu, any suggestions?

Thanks

Coordinator
Oct 15, 2012 at 8:46 PM

Did you enable widget alternates?

Oct 15, 2012 at 9:38 PM

Totally skipped my mind, probably do have it turned off, thanks.

Jan 17, 2013 at 5:46 AM
Jetski5822 wrote:

Okay so MenuItems are rendered out using MenuItem.cshtml, what happens is that recursion is used, so this file would drive each level. You could create an Alternate for this file, and then add a class for each level of recursion you are at.

Hey Nick...or anyone else,

Do you possibly have an example of how this would work in the MenuItem.cshtml file? I've never really had to work with recursion in a View and can't seem to figure out how to set it up in that file. I'm in the same boat as the OP...I simply need to add the class "btn" to the top level menu items. I see where I can define different menuitemlink Views, just not sure how to setup the levels and increment them at the proper place.

Thanks for any help you guys can provide.

Jan 17, 2013 at 6:36 AM

I may have found a solution without using recursion. So far I can't seem to find a way this wouldn't work.

I customized MenuItem.cshtml in my Theme with the following:

        if (Model.Parent.MenuName.ToString() == string.Empty) {
            if (items.Any()) {
                Model.Metadata.Type = "MenuItemLinkdd";
            }
            else {
                Model.Metadata.Type = "MenuItemLink";
            }
        }
        else {
            if (items.Any()) {
                Model.Metadata.Type = "MenuTopItemLinkdd";
            }
            else {
                Model.Metadata.Type = "MenuTopItemLink";
            }
        }

The Model.Parent.MenuName only populates for root level menu items. For all non-root level items, it appears to be empty. So I simply display one set of Views if it's empty and another if they're not. The addition break out for items.Any() is used to display a down arrow for root items with children, or a side arrow for non-root items with children.

If you see any glaring holes in this logic, please let me know...otherwise it appears to work fairly well for me. Thanks again guys!