Programatically add a main menu item

Topics: Writing modules
Sep 18, 2011 at 2:24 PM

I have a module that has some settings.  One of the settings that I would like to add is a checkbox to add or subtract a main menu item and a text box for the meun order.  Collecting the data from the settings is no problem.  How do I programatically set or remove  the menu item?  Thanks!

Coordinator
Sep 21, 2011 at 6:42 PM

You mean an admin menu item? There is already a part for that (admin menu)

Sep 21, 2011 at 8:16 PM

No, I mean on the main menu. Turns out it is really simple. Just add a MainMenu.cs in the root of your module project that implements INavigationProvider. The brelow code queries the content manager, gets the settings, and based on the settings adds the menu item to the main menu.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Orchard.UI.Navigation;
using Orchard.Localization;
using Orchard.ContentManagement;
using Orchard.Data;
using Orchard.Services;

using ThorTech.Testimonial.Models;


namespace ThorTech.Testimonial
{
    public class MainMenu : INavigationProvider
    {

        private readonly IContentManager _contentManager;

        public MainMenu(IContentManager contentManager)
        {
            _contentManager = contentManager;
        }

        public Localizer T { get; set; }
        public void GetNavigation(NavigationBuilder builder)
        {
            bool showOnMainMenu = false;
            decimal menuOrder = 3;

            var siteSettings = _contentManager
                                   .Query()
                                   .ForType("Site")
                                   .List();

            // set up the default
            TestimonialSettingsPart settings = null;

            foreach (ContentItem contentItem in siteSettings)
            {
                settings = contentItem.As<TestimonialSettingsPart>();
                if (settings != null)
                {
                    showOnMainMenu = settings.ShowOnMainMenu;
                    menuOrder = settings.MenuOrder;
                }
            }

            if (showOnMainMenu)
            {
                builder.Add(T("Testimonials"), menuOrder.ToString(), item => item.Action("Index", "Testimonial", new { area = "ThorTech.Testimonial" }));
            }
        }

        public string MenuName { get { return "main"; } }
    }
}

Developer
Sep 21, 2011 at 8:24 PM
Edited Sep 21, 2011 at 8:26 PM

You can remove alot of this code by doing this.

 

namespace ThorTech.Testimonial
{
    public class MainMenu : INavigationProvider
    {
        private readonly IOrchardServices _orchardServices;

        public MainMenu(IOrchardServices orchardServices)
        {
            _orchardServices = orchardServices;
        }

        public Localizer T { get; set; }
        public void GetNavigation(NavigationBuilder builder)
        {
            var testimonialSettingsPart = _orchardServices.WorkContext.CurrentSite.As<TestimonialSettingsPart>()

            if (testimonialSettingsPart.ShowOnMainMenu)
            {
                builder.Add(T("Testimonials"), settings.MenuOrder.ToString(), item => item.Action("Index", "Testimonial", new { area = "ThorTech.Testimonial" }));
            }
        }

        public string MenuName { get { return "main"; } }
    }
}
Sep 21, 2011 at 8:43 PM

Yes, Jetski, that works great.  Thanks for the pointer. 

Just a note for those following along, add

using Orchard;

to get the reference for IOrchardServices and the builder.Add should be:

                builder.Add(T("Testimonials"), testimonialSettingsPart.MenuOrder.ToString(), item => item.Action("Index", "Testimonial", new { area = "ThorTech.Testimonial" }));

Again, thank for all of the help!

May 30, 2014 at 8:54 AM
For anyone finding this old thread please note the following:
"From Orchard 1.5.0 onwards, INavigationProvider isn't used to build menus on the front end (it is still used to build the admin menu for the Dashboard though). You need to implement either IMenuProvider or INavigationFilter." (source: stackoverflow