how do you override the rendering of the Navigation zone in Orchard CMS?
Asked Answered
D

2

14

I'm new to Orchard, so I probably have no idea what I'm doing.

I've figured out how to override different shapes but putting a cshtml file in the View folder with the same name as the shape.

Also, I found the Menu and MenuItem shape cshtml files under the Core Orchard files.

However, I don't see a shape named Navigation and I don't really understand how Zones work.

I searched the code and couldn't figure out exactly how the Navigation is rendered, though I did find some of the code.

The reason that I want to override the Navigation rendering is that it renders a DIV and a NAV tag around the UL. I would prefer to just render the NAV and UL.

Discountenance answered 29/5, 2011 at 22:13 Comment(0)
C
11

Zones are also shapes, but they are declared in code (Core/Shapes/CoreShapes.cs), not in .cshtml files like most of shapes. Also, there is no shape called Navigation, as zones are created dynamically at runtime - names of those are provided by the theme used.

Zones have default alternates in the form Zone__[ZoneName]. It means you just need to put Zone-Navigation.cshtml file in /Views folder in your theme folder to override Navigation zone rendering.

Clerkly answered 29/5, 2011 at 22:42 Comment(8)
thanks. That worked, but I don't how to render the menu shape with the navigation data or how to access the navigation data in order to build the menu myself. Calling @Display(Model.Menu) doesn't work.Discountenance
Menu (which render the 'nav' element) and MenuItem (which renders a single item) are shapes, so you can override them by placing a Menu.cshtml and/or MenuItem.cshtml files in your theme /View folder. Take a look at how the default ones are rendered - you can find them in Core/Shapes/Views folder. BTW - @Display() method is used to render a shape object (and such should be provided). If you need to render the zone contents by hand - cast a Model (which holds current zone shape object) to IEnumerable<dynamic> and call Display(item) for each item.Clerkly
For clarification: Each shape object (which is available inside .cshtml file as Model property) implements an IEnumerable<dynamic> interface and can contain other, child shapes (eg. the menu shape in Navigation zone). That's why you can freely cast it to IEnumerable<dynamic> and access children (if any) in foreach loop.Clerkly
That's interesting and I didn't know that. Still not sure I completly understand it, but Menu.cshtml and MenuItem.cshtml actually do what I want already. I would only want to override them if I couldn't achieve the change that I want in the Navigation. The real problem is that as Navigation is rendered now, it renders a DIV that surrounds all of the contents, which I don't want. I can override Navigation using Zone-Navigation.cshtml like you suggested, but now I don't know how to get Menu.cshtml to render properly. I tried calling @Display(Model.Menu) but nothing gets rendered at all.Discountenance
I just discovered that if I create Zone-Navigation.cshtml and inside this file I call @DisplayChildrent(Model) it does exactly what I was trying to do. I just don't understand exactly why? I poked around in the Model object and couldn't find any data so I don't know how DisplayChildren knew to display a Menu shape or where it pulled the Menu data from to build the shape. I can't figure out what information is in the ModelDiscountenance
One more thing, as an experiment I did try casting the Model to an IEnumerable<dynamic> and I ran a foreach() loop on it. After I wrote the loop, I wasn't sure what to do with the element(s) that I was going to iterate over, so I just called ToString(). When I did this, there was one item and it was named ShapeProxy3e96a40aca6c4604a7fc374cf0889153. I tried looking for different properties like .Text but I wasn't sure what to do with it. I tried embeding another foreach loop thinking that it might have had a Menu child which had MenuItem children but that didn't work or I didn't do it correctlyDiscountenance
This worked!@{ IEnumerable<dynamic> m = (IEnumerable<dynamic>)Model; } <ol> @foreach (var i in m) { <li> <ol> @foreach (var j in i) { <li>@j.Text</li> } </ol> </li> } </ol>Discountenance
Glad you made it work! @DisplayChildren method is declared on Orchard.Mvc.ViewEngines.Razor.WebViewPage object. It just loops over the shape and call Display(...) for each object. Shapes are dynamic and most of their properties are added at runtime, so there's not much you can see in debugger, unfortunately. Menu shape is created and added to Navigation zone in Orchard.UI.Navigation.MenuFilter class (lines 44-52). Items are fetched via INavigationManager.BuildMenu() method, call to which you can also see there.Clerkly
N
1

If you are using the latest 1.1.3 release you can use the new shape tracing tool from the designer tools module. It provides a list of URL alternates to name your template in order to override the default rendering.

Nonbelligerent answered 29/5, 2011 at 22:45 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.