Orchard Core CMS Theme Mega Menu (Advanced Menu Theming)

435 Views Asked by At

For the purposed of learning I am trying to take the general theme of my companies website and convert it into an Orchard Core Theme (version 1.2.2 (can't go to 1.3 yet because of VS version but can if it solves my issues.)). The first issue I have run into is the mega menu. Ultimately I am looking to have the mega menu have a pop-down on mouse over into a megamenu panel that has 3 columns. The following is how I am trying to do it but happy to hear suggestions on alternate ways of doing it.

My intent is, in the menu system, I plan on making a 3 level menu. First (level 0) is the main menu title such as "Home" with the the rendered menuitemlink. The second menu level (Level 1) would be almost conceptual or a place holder. It would be named for one of the 3 columns. (Column1, Column2, Column3). In the theme this column wouldn't have a menuitemlink but would create some divs that produce the columns. And the 3rd level (level 2) would be a simple li tag with the the rendered menuitemlink.

Documentation I am using: https://docs.orchardcore.net/en/dev/docs/reference/modules/Menu/

To do this I setup 3 Alternate files (Hope I am getting the terminology right) using razor.

The following is the code for each:

Menu-MainMenu.cshtml

@{
    TagBuilder tag = Tag(Model, "ul");
    tag.AddCssClass("nav navbar-nav pull-right");

    foreach (var item in Model.Items)
    {
        tag.InnerHtml.AppendHtml(await DisplayAsync(item));
    }
}

@tag

MenuItem-MainMenu.cshtml

@using OrchardCore.ContentManagement
@{
    TagBuilder topTag = new TagBuilder("div");


    if (Model.Level == 0)
    {
        topTag = Tag(Model, "li");
        topTag.AddCssClass("primary nekoMegaMenuTrigger");

        Model.Metadata.Alternates.Clear();
        Model.Metadata.Type = "MenuItemLink";

        topTag.InnerHtml.AppendHtml(await DisplayAsync(Model));

        if ((bool)(Model.HasItems))
        {
            TagBuilder MegaBlockTag = new TagBuilder("div");
            MegaBlockTag.AddCssClass("nekoMegaMenu subMenu");
            topTag.InnerHtml.AppendHtml(MegaBlockTag);

            TagBuilder RowTag = new TagBuilder("div");
            RowTag.AddCssClass("Row");
            MegaBlockTag.InnerHtml.AppendHtml(RowTag);

            //Column One Setup
            TagBuilder ColumnOne = new TagBuilder("ul");
            TagBuilder C1InnerDiv = new TagBuilder("div");
            C1InnerDiv.AddCssClass("megaInner clearfix");
            TagBuilder C1OuterDiv = new TagBuilder("div");
            C1OuterDiv.AddCssClass("col-sm-4");
            C1OuterDiv.InnerHtml.AppendHtml(C1InnerDiv);
            C1InnerDiv.InnerHtml.AppendHtml(ColumnOne);


            //Column Two Setup
            TagBuilder ColumnTwo = new TagBuilder("ul");
            TagBuilder C2InnerDiv = new TagBuilder("div");
            C2InnerDiv.AddCssClass("megaInner clearfix");
            TagBuilder C2OuterDiv = new TagBuilder("div");
            C2OuterDiv.AddCssClass("col-sm-4");
            C2OuterDiv.InnerHtml.AppendHtml(C2InnerDiv);
            C2InnerDiv.InnerHtml.AppendHtml(ColumnTwo);

            //Column Three Setup
            TagBuilder ColumnThree = new TagBuilder("ul");
            TagBuilder C3InnerDiv = new TagBuilder("div");
            C3InnerDiv.AddCssClass("megaInner clearfix");
            TagBuilder C3OuterDiv = new TagBuilder("div");
            C3OuterDiv.AddCssClass("col-sm-4");
            C3OuterDiv.InnerHtml.AppendHtml(C3InnerDiv);
            C3InnerDiv.InnerHtml.AppendHtml(ColumnThree);

            RowTag.InnerHtml.AppendHtml(C1OuterDiv);
            RowTag.InnerHtml.AppendHtml(C2OuterDiv);
            RowTag.InnerHtml.AppendHtml(C3OuterDiv);


            foreach (var item in Model.Items)
            {
                System.Collections.Generic.List<OrchardCore.DisplayManagement.IPositioned> subItems = (System.Collections.Generic.List<OrchardCore.DisplayManagement.IPositioned>)item.Items;
                ContentItem contentItem = item.ContentItem;
                var link = contentItem.Content["LinkMenuItemPart"];
                switch (contentItem.Content["LinkMenuItemPart"].Name.ToString())
                {
                    case "Column1":
                        if ((bool)item.HasItems)
                        {
                            foreach (var subItem in item.Items)
                            {
                                TagBuilder subTag = Tag(subItem, "li");
                                ColumnOne.InnerHtml.AppendHtml(subTag);
                                subTag.InnerHtml.AppendHtml(await DisplayAsync(subItem));
                            }
                        }
                        break;

                    case "Column2":
                        if ((bool)item.HasItems)
                        {
                            foreach (var subItem in item.Items)
                            {
                                TagBuilder subTag = Tag(subItem, "li");
                                ColumnTwo.InnerHtml.AppendHtml(subTag);
                                subTag.InnerHtml.AppendHtml(await DisplayAsync(subItem));
                            }
                        }
                        break;

                    case "Column3":
                        if ((bool)item.HasItems)
                        {
                            foreach (var subItem in item.Items)
                            {
                                TagBuilder subTag = Tag(subItem, "li");
                                ColumnThree.InnerHtml.AppendHtml(subTag);
                                subTag.InnerHtml.AppendHtml(await DisplayAsync(subItem));
                            }
                        }
                        break;

                    default:
                        break;
                }
            }
        }
    }
}

@topTag

MenuItemLink-MainMenu.cshtml

 @using OrchardCore.ContentManagement
 
 @{
     ContentItem contentItem = Model.ContentItem;
     var link = contentItem.Content["LinkMenuItemPart"];
 }
 
 @if ((bool)(Model.HasItems))
 {
     <a class="nav-link dropdown-toggle" data-toggle="dropdown" href="@Url.Content((string)link.Url)">@link.Name<b class="caret"></b></a>
 }
 else
 {
     <a class="firstLevel" href="@Url.Content((string)link.Url)">@link.Name</a>
 }

The issue with this code happen within the switch statement. item from the for each Model.Items does not have its subitems. If you debug and watch the variable it has the attribute but the items are not listed. Below is a copy of the debug/watch of Items of item:

Items   {System.Collections.Generic.IEnumerable<object>}    System.Collections.Generic.IEnumerable<dynamic> {System.Collections.Generic.IEnumerable<object>}

If you debug/watch item.Items you get:

error CS1061: 'object' does not contain a definition for 'Items' and no accessible extension method 'Items' accepting a first argument of type 'object' could be found (are you missing a using directive or an assembly reference?)

I have considered using the alternate file for each level but I don't understand how it works and not sure how I would get the end link inside the required HTML. (I will be playing with this to see if I can figure it out but wanted to get this question posted in case this way is correct and I am just making a mistake. )

Any help would be appreciated.

0

There are 0 best solutions below