This project is read-only.

Dynamically add menu item

Dec 20, 2011 at 5:24 PM

Is it possible to dynamically a menu item to the menu? For example: i want to add some related items of the current user to to the menu as submenuitems.

I want to do this from a other module so i don't have to change this better menus module

Coordinator
Dec 20, 2011 at 5:27 PM

Hmm, I think you could create a new menu item type (right now there are content item and custom url menu item types).  It would definitely take some work, but I tried to make it so you could do it from another module.  Let me know if you have questions or problems.

Dec 20, 2011 at 6:51 PM
Edited Dec 20, 2011 at 6:59 PM

ok thanks for your fast response! Can you give me some advice how to start? Because i'm not sure how to do this.

The nicest thing would be implement a INavigationProvider but i'm affraid this won't work with your module

Coordinator
Dec 20, 2011 at 7:10 PM

Honestly, I was steering you in the wrong direction anyway.  It would be tough as it is now to create a custom menu item type without editing my module.  I'll have to change that.

For the time being, I was actually about to suggest that you override a method in this file in the better menu module: ~/Services/MenuService.cs.

You can override the BuildNavigation method in there to do something special for your content type, something like this:

private void BuildNavigation(NavigationBuilder builder, RelatedContentPart parent, string parentPosition = "")
        {
            var menuItems = _relatedContentService
                .GetRelatedItems(parent, "menu-items")
                .Select(ri => _contentManager.Get<BetterMenuItemPart>(ri.Id))
                .OrderBy(mi => mi.SortOrder)
                .ToList();
            for (int i = 0; i < menuItems.Count(); i++)
            {
                var menuItem = menuItems[i];
                var text = new LocalizedString(HttpUtility.HtmlEncode(menuItem.Text));
                var position = parentPosition + i.ToString();                
                builder.Add(text, position, item =>
                    {
                        if (menuItem.MenuItemType == MenuItemType.CustomLink)
                            item.Url(menuItem.Url);
                        else
                        {
                            var metadata = _contentManager.GetItemMetadata(menuItem.RelatedItem.Value);
//check to see if this is your content item or type, and do something special to insert sub-navigation items
                            if (metadata.DisplayRouteValues != null)
                            {
                                item.IdHint(menuItem.RelatedItem.Value.Id.ToString());
                                item.Action(metadata.DisplayRouteValues);
                            }

                        }
                        BuildNavigation(item, menuItem.As<RelatedContentPart>(), position + ".");
                    });                
            }            
        }

Dec 20, 2011 at 7:58 PM

ah ok nice! i tried it and it worked! It would be nice if you manage to change this so we can add new items from other module without overriding the whole service. nevertheless thank you very much for you advice and great work!

Coordinator
Dec 20, 2011 at 8:06 PM
Please let me know how you would like to see this surfaced in such a way that you would be able to access it from another module.
Dec 20, 2011 at 8:27 PM

Well it would be nice if can implement a INavigationProvider and add dynamically items to it but i don't know if that's possible. This would be the nicest i can think of at the moment because that's the default way of adding items to the default orchard menu dynamically.