Arrow icon
Back to Insights

Adding a starting node for the Orchard Navigation Menu Widget

May 16, 2013
Arra Derderian

On many websites I have built there is a need to create Footer Navigation that looks like the following :

This presents a challenge in Orchard because the navigation elements span multiple zones and require specific formatting for each zone. As you can see above, there are three distinct zones in the footer for navigation elements to appear. The way I would think to solve this is to create a theme that has three distinct zones and then add Menu Widgets inside each one to render the portions of the "main" menu that are required.

The problem with this approach is that the Menu Widget is designed to be placed on secondary pages and then only display items by the "selected start level" and "display level" options. This works well for secondary navigation menu on all pages by placing your menu widget in a layer only visible on secondary pages (Layer Rule : not url ('~/')). You then configure the widget with these settings :

This will render only the items underneath the current page starting at level 2 in the menu hierarchy, and then render everything underneath it. Great. But in a scenario where you want to output the navigation sub menus in a footer for all pages and not just the selected one you need another option. Luckily, it is only one option we need to add :

As you can see I added the "Starting Position" option to the Menu Widget. This is an indicator for the menu driver to only render based on a set position. This position lets us add a bunch of menu widgets to our footer zone as detailed above in the widgets image. For each menu widget we set the starting position field to the corresponding position in your menu. This way we can have all of our application menus linked and changing them will automatically trickle through all aspects of the site.

The code changes for Orchard 1.6.1 that are required are the following :

1. Add a new property in Orchard.Core/Navigation/Models/MenuWidgetPart.cs, Orchard.Core/Navigation/Models/MenuWidgetPartRecord.cs, and  Orchard.Core/Navigation/ViewModels/MenuWidgetViewModel.cs for StartingNode. It will be of type Int32. After you do this go back to Orchard.Core/Navigation/Drivers/MenuWidgetPartDriver.cs and add the StartingNode property to be mapped in all the driver methods. (Editor, Editor, Importing, Exporting). Just copy the code for the StartLevel property.

2. Orchard.Core/Navigation/Drivers/MenuWidgetPartDriver.cs

Line 122  in the Display Driver for the widget :

if (part.StartingNode > 0) {

     topLevelItems = topLevelItems.Where(p => p.Position == part.StartingNode.ToString()).ToList();

}

else if (part.StartLevel > 1 && selectedPath != null) {

       // the selected path will return the whole selected hierarchy

      // intersecting will return the root selected menu item

      topLevelItems = topLevelItems.Intersect(selectedPath.Where(x => x.Selected)).ToList();

}

We add an "if" statement before the code that checks for a selected path to filter the items by. This will let us know if the person wishes to filter by a Starting Node. If they do we filter the toplevelItems by the Position. This way only the items for that node are returned. We then let the code continue on as normal.

3. Orchard.Core/Navigation/Migrations.cs

Add a migration to add your new property to the MenuWidgetPartRecord table. This will persist your new setting.

public int UpdateFrom3() {

SchemaBuilder.AlterTable("MenuWidgetPartRecord", table => table

.AddColumn("StartingNode", DbType.Int32)

);

return 4;

}

4. Orchard.Core/Views/EditorTemplates/Parts.MenuWidget.Edit.cshtml

Lastly, you need to edit the view template file for the Widget Editor to add your new field.

  <fieldset>

       <label for="@Html.FieldIdFor(m => m.StartingNode)">@T("Starting Position")</label>

       @Html.TextBoxFor(m => m.StartingNode, new { @class = "text text-small" })

       <span class="hint">@T("The number of levels to return, \"0\" meaning all nodes.")</span>

   </fieldset>

Rebuild. And you should have all the options you need. You may need to delete your mappings.bin file or restart the site so the new properties are brought in to Orchard. Your migration will run automatically on the next refresh. You can now render your sub menus as you see fit.

About the Author:

Arra Derderian serves as the President and as a Lead Technical Architect for Cloud Construct. As a founder at Cloud Construct, Arra is involved in all levels of the business from new project engagements, project planning, and development.

He also serves as the founder of the Boston Orchard CMS User Group and is a member of the Windows Azure Insiders group.

Arra graduated from Northeastern University School with a Bachelor of Science degree in Computer Science.

Author Photo
Arra Derderian
Founder & Chairman
Arrow icon
Back to Insights

Let's talk about your project

Drop us a note
Arrow
Or call us at:  
1.617.903.7604

Let's talk about
your project

Drop us a note
Arrow
Or call us at:
1.617.903.7604

Let's talk about your project

Drop us a note
Arrow
Or call us at:  
1.617.903.7604