|Number of votes:||7|
The main menu is usually a quite important part of your website. A traditional top/main menu typically displays section pages, and can easily be done with EPiServer. But what if you would like the menu items to be drag and droppable, and possible non-hierarchical? I thought I’d share some code on how to use a content area as a main menu, which will enable editors to drag and drop pages into the menu and customize it with ease.
In order to accomplish this, I’ve created a controller which convert pages into view models. The view models are then rendered inside a content area which is located in the header view of my site.
First of, the menu item model. This is pretty basic, with string properties for url and heading, and a bool property to set whether the link is currently selected or not.
Secondly, the controller. To be able to make this work with all page types, I have set the PageController typed to SitePageData, which in this case is a base class for all page types. As for the TemplateDescriptor, I’ve set the TemplateTypeCategory to MvcPartialController. This way, it will render as a partial view. I’ve also set Tags to “mainmenu”, so that it will only match content areas with that certain tag. Inherited is set to “true” so that it will match all types that inherit from SitePageData. I also needed to make sure that menu items are active when a child page is selected, but since this is a (possible) non-hierarchical menu, I also needed to make sure that only the closest menu item is set as active, as a page might be a descendent of several menu items. I’ve tried my best to describe this in the inline comments.
In the corresponding view, a link is rendered based on the properties in the model, and the Active property is used to add a css class. If active, a sky blue background should be displayed.
At this point, drag and drop of pages will work if the current content area is placed within a page view. However, since this should be used as a top menu, I want to put it in my header view. In order to accomplish this, I’ve created a layout model, which will be accessible for partial views such as the header or footer. This will contain a ContentArea property, which will be populated by a ContentArea property on the StartPage. I’ve chosen to do it this way to keep it simple, but you could take a look at the Alloy MVC templates(highly recommended!) to see a different, more dynamic approach on how to handle this. Please note that in a real-world scenario, the model would most likely contain more properties.
The (really, really simple) layout model:
Then I’ve created a base class for all my PageControllers. This will make sure the layout model is populated with the correct data, no matter which page you are currently on.
And in my header view, I’ll render the ContentArea property. I’ve added some custom tags and css classes in order to make it look nice in both edit mode and view mode (you can read more about those settings here). Also notice that I set the Tag to “mainmenu”.
In order to get on-page-editing working, connections are added from the page model to my view model. I do this in the start page controller, since my property is located in my StartPage type.
Final result – view mode:
And in edit mode:
Keep in mind that since a content area is used, you have the possibility to extend the menu options by using blocks. How about a DropDownMenuItemBlock? Or maybe a MegaMenuItemBlock?