Ticket (Solved)

Alternates for menus

I'm trying to find the right alternate name for menu's. I added two menu widgets to my Navgation Zone. I named them differently.

If I debug I can see that the Menu name is the same for both menu widgets. Not sure why, but that also gives me the same alternates for both widgets. I'd like to have different views for the two menus.

What can I do about this?

Re: Alternates for menus

Here, as i remember. You have the Title of your widget, the Name that is the technical name, and the For Menu where you can select the right menu. So, you need to define 2 menus through the navigation page and select in each widget the right one. But maybe you want to display the same menu in 2 different ways and places.

Normally, the 1st alternate you can use is with the technical name Widget-Name-MyName.cshtml. Try with the shape tracing module, you will see all the alternates and view models. But here, with this alternate, the default is @Display(Model.Content). So, you will have to deal with Model.Content.Items that are shapes and one of them is the menu, so here not not so easy...

Maybe better to use this alternate Parts.MenuWidget.cshtml that will be common to your 2 menus. But here you can do something like this var name = @Model.ContentItem.WidgetPart.Name to get the technical name of the current widget, and then differentiate the beharvior.

Then you can deal with Model.Menu, Model.Menu.Items...

Best

Thursday, March 3, 2016 12:25:18 AM byjtkech
  • jtkech
  • Lv. 13 Rookie
  • Total EXP: 1028

Re: Alternates for menus

It makes sense, since two menu widgets can point to the same menu. As Jean Thierry mentions, you can specify a Name for the menu widget itself. Be sure to enable the Widget Alternates feature as well.

Additionally, the IDeliverable.Bits module may be useful. It provides a feature called Navigation Bits which it adds additional alternates to the Parts_MenuWidget, Menu and MenuItem shapes based on widget name, menu name and zone name, and even the menu item level for more advanced scenarios. There is no documentation right now, but if you look at the MenuWidgetShapeAlternates.cs class in the Navigation/Shapes folder, you should be able to infer the available alternates. Or use the debugger and discover the available alternates at runtime.

Saturday, March 5, 2016 12:11:54 PM bysfmskywalker

Re: Alternates for menus

Thanks both! So how would I change e.g. the MenuItem template before using the DisplayChildren? Because I need to render the children in a different way then the 'normal' menu items.

 if (HasText(renderedMenuItemLink))
    {
        <div class="hold">
            <span class="title">@renderedMenuItemLink</span>

            @if (items.Any())
            {
                // TODO: should change the template before rendering children??
                <ul>
                    @DisplayChildren(Model)
                </ul>
            }

        </div>

            }
        }

Any suggestions?

Sunday, March 13, 2016 3:05:58 PM bykonstrui

Re: Alternates for menus

So, as said by Sipke, the class MenuWidgetShapeAlternates : IShapeTableProvider provides the alternates you need. Otherwise, directly in a razor view, you can use one of the 2 following ways.

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

Or

    ...Metadata.Alternates.Add("Something");

Note: Here, i will use the 2nd way because with the 1st one i've got some error (but only when shape tracing is enabled).

So, i assume you use the same menu in your 2 widgets, and that's why you have the same alternates for the menu items. Menu items are not so easy to understand under shape tracing. See in MenuItem.cshtml view, the metadata type is overridden. That's why you only see the MenuItemLinkshapes under shape tracing.

One solution that works (tried in dev branch): Copy in your theme these 3 razor views Parts.MenuWidget.cshtml, MenuItem.cshtml and MenuItemLink.cshtml. Rename the 2 last ones with MenuItem-side-menu and MenuItemLink-side-menu. Here, change the file names according to your widget tecnical names.

Then, in Parts.MenuWidget.cshtml use this:

@using Orchard.Utility.Extensions;
@{
    var name = Model.ContentItem.WidgetPart.Name;
    var alternate = "MenuItem__" + ((string)name).HtmlClassify().Replace("-", "__");

    foreach (var item in Model.Menu.Items) {
        item.Metadata.Alternates.Add(alternate);
    }
}
@Display(Model.Menu)

And in MenuItem-side-menu add this line (and do other things you want):

    Model.Metadata.Alternates.Clear();
    Model.Metadata.Type = "MenuItemLink";
    // add this line
    Model.Metadata.Alternates.Add("MenuItemLink__side__menu");

Then, in MenuItemLink-side-menu do what you want.

Best

Monday, March 14, 2016 12:30:42 AM byjtkech
  • jtkech
  • Lv. 13 Rookie
  • Total EXP: 1028

Re: Alternates for menus

Hi,

Thanks for the reply. I indeed was able to use the ShapeTableProvider to add more alternates. My question though is how I can change the layout for the, let's say, 2nd level of menu items of my 'second' menu.

So I use these alternates for my second menu:

Menu Menu-WidgetName-SubMenu.cshtml

MenuItem MenuItem-WidgetName-SubMenu.cshtml

MenuItemLink MenuItemLink-WidgetName-SubMenu.cshtml

If I change something in the e.g. MenuItem-WidgetName-SubMenu.cshtml the markup for the children will be the same. So @DisplayChildren(Model) will use the same alternate resulting in the same markup for all levels of the menu.

What would be the best practice to solve this? So let's say I want my toplevel menu items to be bold, but the second level should be rendered as normal.

Cheers.

Wednesday, March 16, 2016 10:33:42 PM bykonstrui

Re: Alternates for menus

Oh, i see.

So, in your MenuItem alternate, in the Model, normally there is a property you can use Model.Level.

Because when MenuItem.cshtml call @DisplayChildren(Model), the same alternate will be used at another level. So, here you can use var level = Model.Level?? 0;. Then, depending on the result, after, in the same MenuItem.cshtml, you can select MenuItemLink or a different alternate.

Best

Wednesday, March 16, 2016 11:05:35 PM byjtkech
  • jtkech
  • Lv. 13 Rookie
  • Total EXP: 1028

Re: Alternates for menus

Ah... well. I'm close to getting my head around it ;) I've defined this alternate in my ShapeTableProvider which gives me indeed the option to specify also the level:

displaying.Shape.Metadata.Alternates.Add("MenuItem__WidgetName__" + EncodeAlternateElement(widgetName) + "__level__" + level);

Now I can create this alternate razor template and change the markup.

Thanks for your patience though! Up to the next challenge. ;)

Best, Daniel

Wednesday, March 16, 2016 11:15:22 PM bykonstrui

Re: Alternates for menus

Oh, just seen your previous comment, cool. But worth to know there is a Level property in the MenuItem model. Best.

Wednesday, March 16, 2016 11:18:44 PM byjtkech
  • jtkech
  • Lv. 13 Rookie
  • Total EXP: 1028

Re: Alternates for menus

Just seen the MenuWidgetShapeAlternates class and how it adds recursively alternates through all the items levels. Wow, i think you can mark this ticket as answered by @sfmskywalker. ;)

Thursday, March 17, 2016 8:18:10 AM byjtkech
  • jtkech
  • Lv. 13 Rookie
  • Total EXP: 1028

Post a reply

You need to be signed in to post a reply.

Sign In