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.

Piotr Szmyd
  • 13,371
  • 6
  • 44
  • 61
Zack
  • 2,291
  • 2
  • 23
  • 38

2 Answers2

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.

Piotr Szmyd
  • 13,371
  • 6
  • 44
  • 61
  • 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. – Zack May 30 '11 at 00:54
  • 4
    *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 and call Display(item) for each item. – Piotr Szmyd May 30 '11 at 02:42
  • For clarification: Each shape object (which is available inside .cshtml file as Model property) implements an IEnumerable interface and can contain other, child shapes (eg. the menu shape in Navigation zone). That's why you can freely cast it to IEnumerable and access children (if any) in foreach loop. – Piotr Szmyd May 30 '11 at 02:48
  • 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. – Zack May 30 '11 at 15:48
  • 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 Model – Zack May 30 '11 at 16:05
  • One more thing, as an experiment I did try casting the Model to an IEnumerable 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 correctly – Zack May 30 '11 at 16:21
  • This worked!`@{ IEnumerable m = (IEnumerable)Model; }
      @foreach (var i in m) {
      1. @foreach (var j in i) {
      2. @j.Text
      3. }
    1. }
    `
    – Zack May 30 '11 at 16:29
  • 1
    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. – Piotr Szmyd May 30 '11 at 17:06
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.

David Glenn
  • 24,412
  • 19
  • 74
  • 94