Forumla / Example for Side-bar Navigation?

Topics: Customizing Orchard, General, Writing themes
Jun 6, 2013 at 12:01 PM
Has anyone got an example or formula for side-bar navigation? One poster seemed to have been looking at it on StackOverflow:

http://stackoverflow.com/questions/12013440/orchard-cms-sidebar-menu

and it's mentioned in the requirements documentation:

http://docs.orchardproject.net/Documentation/navigation

But I can't find any worked examples. The requirement is, well, side-bar navigation, skinned by the site theme.

Cheers,
- SteveN
Jun 6, 2013 at 4:57 PM
Edited Jun 6, 2013 at 5:00 PM
Yes...I'm running it on our intranet website which was themed from this template: https://wrapbootstrap.com/theme/acme-responsive-admin-template-WB0JLR295

I created new menus in Navigation, then added them to the AsideFirst zone on new widget layers with layer rules. The layer rules define a url pattern
~/EIS/*
~/Metrics/*
~/Setup/*
I actually have 3 side menus that change depending on where you are on the site.

There is a custom menu template for each menu in my theme's Views folder

EIS Menu - Menu-e-i-s-menu.cshtml
Metrics Menu - Menu-metrics-menu.cshtml
Setup Menu - Menu-setup-menu.cshtml

These templates look like this:
@{
    // odd formatting in this file is to cause more attractive results in the output.
    var items = (IEnumerable<dynamic>)Enumerable.Cast<dynamic>(Model);
}
@{
    if (!HasText(Model.Text)) {
    @DisplayChildren(Model)
    }
    else {
        string requestUrl = Request.Path.Replace(Request.ApplicationPath, string.Empty).TrimEnd('/').ToUpperInvariant();
        string modelUrl = Model.Href.Replace(Request.ApplicationPath, string.Empty).TrimEnd('/').ToUpperInvariant();
        if (requestUrl.StartsWith(modelUrl)) {
            Model.Classes.Add("active");
        }
        var tag = Tag(Model, "li");
    @tag.StartElement
            
@* morphing the shape to keep Model untouched*@
        Model.Metadata.Alternates.Clear();
        Model.Metadata.Type = "MenuSideItemLink";

        @Display(Model)

        if (items.Any()) {
            <ul class="dropdown-menu">
                @DisplayChildren(Model)
            </ul>
        }
    @tag.EndElement
    }
}
You can see that it's using a template named MenuSideItemLink to render the menu items. That template looks like this:
<a href="@Model.Href">
    @if(Model.Text.ToString() == "Dashboard") {
        <i class='icon-dashboard'></i>
    }
    else if (Model.Text.ToString() == "Calendar") {
        <i class='icon-calendar'></i>
    }
    <span class="hidden-tablet">&nbsp;@Model.Text</span>
</a>
there's a whole bunch of if/then statements in there to render the proper icon (need to change that to a switch statement to make it easier), but that should give you an idea of how to do it.

Your layout.cshtml will have to take into account placing the AsideFirst zone of course...I'm using Bootstrap, so:
<div class="container-fluid" style="padding-top: 20px;">
    <div class="row-fluid">
        @if (Model.AsideFirst != null) {
            <!-- start: Main Menu -->
            <div id="sidebar-left" class="span1">
                <div class="nav-collapse sidebar-nav">
                    @Zone(Model.AsideFirst)
                </div>
            </div>
            <!-- end: Main Menu -->
        }
        <noscript>
            <div class="alert alert-block @(HasText(asideClass) ? asideClass == "aside-1" ? "span11" : asideClass == "aside-2" ? "span9" : asideClass == "aside-12" ? "span8" : "span12" : "")">
                <h4 class="alert-heading">
                    Warning!</h4>
                <p>
                    You need to have <a href="http://en.wikipedia.org/wiki/JavaScript" target="_blank">JavaScript</a>
                    enabled to use this site.</p>
            </div>
        </noscript>
        <!-- start: Content -->
        <div id="content" class="@(HasText(asideClass) ? asideClass == "aside-1" ? "span11" : asideClass == "aside-2" ? "span9" : asideClass == "aside-12" ? "span8" : "span12" : "")">
            @if (Model.Featured != null) {
                <div class="row-fluid">
                    @Zone(Model.Featured)
                </div>
                <hr />
            }
            @if (Model.BeforeMain != null) {
                <div class="row-fluid">
                    @Zone(Model.BeforeMain)
                </div>
                <hr />
            }
            <div class="row-fluid">
                @if (Model.Messages != null) {
                    @Zone(Model.Messages)
                }
                <!--[if lte IE 7]>
                    <div class="alert alert-block alert-error iewarning" style="color: #b94a48 !important;"><h3 class="center">STOP!</h3><p>Before proceeding, you must follow the steps below:</p><ol><li>Open the "Tools" menu (Alt+T)</li><li>Select "Compatibility View Settings"</li><li>Uncheck the box labeled "Display intranet sites in Compatibility View"</li></ol><p>Please note that this site is not compatible with Internet Explorer 7</p></div>
                <![endif]-->
                @if (Model.BeforeContent != null) {
                    @Zone(Model.BeforeContent)
                }
                @if (Model.Content != null) {
                    @Zone(Model.Content)
                }
                @if (Model.AfterContent != null) {
                    @Zone(Model.AfterContent)
                }
            </div>
            @if (Model.AfterMain != null) {
                <hr />
                <div class="row-fluid">
                    @Zone(Model.AfterMain)
                </div>   
            }
            @if (Model.TripelFirst != null || Model.TripelSecond != null || Model.TripelThird != null) {
                <hr />
                <div class="row-fluid">
                    @if (Model.TripelFirst != null) {
                        <div class="@(HasText(tripelClass) ? tripelClass == "tripel-12" || tripelClass == "tripel-23" || tripelClass == "tripel-13" ? "span6" : tripelClass == "tripel-123" ? "span4" : "span12" : "")">
                            @Zone(Model.TripelFirst)
                        </div>
                    }
                    @if (Model.TripelSecond != null) {
                        <div class="@(HasText(tripelClass) ? tripelClass == "tripel-12" || tripelClass == "tripel-23" || tripelClass == "tripel-13" ? "span6" : tripelClass == "tripel-123" ? "span4" : "span12" : "")">
                            @Zone(Model.TripelSecond)
                        </div>
                    }
                    @if (Model.TripelThird != null) {
                        <div class="@(HasText(tripelClass) ? tripelClass == "tripel-12" || tripelClass == "tripel-23" || tripelClass == "tripel-13" ? "span6" : tripelClass == "tripel-123" ? "span4" : "span12" : "")">
                            @Zone(Model.TripelThird)
                        </div>
                    }
                </div>
            }
            @if (Model.FooterQuadFirst != null || Model.FooterQuadSecond != null || Model.FooterQuadThird != null || Model.FooterQuadFourth != null) {
                <hr />
                <div class="row-fluid">
                    @if (Model.FooterQuadFirst != null) {
                        <div class="@(HasText(footerQuadClass) ? footerQuadClass == "split-1" || footerQuadClass == "split-2" || footerQuadClass == "split-3" || footerQuadClass == "split-4" ? "span12" : footerQuadClass == "split-12" || footerQuadClass == "split-13" || footerQuadClass == "split-14" || footerQuadClass == "split-23" || footerQuadClass == "split-24" || footerQuadClass == "split-34" ? "span6" : footerQuadClass == "split-123" || footerQuadClass == "split-124" || footerQuadClass == "split-134" || footerQuadClass == "split-234" ? "span4" : "span3" : "")">
                            @Zone(Model.FooterQuadFirst)
                        </div>
                    }
                    @if (Model.FooterQuadSecond != null) {
                        <div class="@(HasText(footerQuadClass) ? footerQuadClass == "split-1" || footerQuadClass == "split-2" || footerQuadClass == "split-3" || footerQuadClass == "split-4" ? "span12" : footerQuadClass == "split-12" || footerQuadClass == "split-13" || footerQuadClass == "split-14" || footerQuadClass == "split-23" || footerQuadClass == "split-24" || footerQuadClass == "split-34" ? "span6" : footerQuadClass == "split-123" || footerQuadClass == "split-124" || footerQuadClass == "split-134" || footerQuadClass == "split-234" ? "span4" : "span3" : "")">
                            @Zone(Model.FooterQuadSecond)
                        </div>
                    }
                    @if (Model.FooterQuadThird != null) {
                        <div class="@(HasText(footerQuadClass) ? footerQuadClass == "split-1" || footerQuadClass == "split-2" || footerQuadClass == "split-3" || footerQuadClass == "split-4" ? "span12" : footerQuadClass == "split-12" || footerQuadClass == "split-13" || footerQuadClass == "split-14" || footerQuadClass == "split-23" || footerQuadClass == "split-24" || footerQuadClass == "split-34" ? "span6" : footerQuadClass == "split-123" || footerQuadClass == "split-124" || footerQuadClass == "split-134" || footerQuadClass == "split-234" ? "span4" : "span3" : "")">
                            @Zone(Model.FooterQuadThird)
                        </div>
                    }
                    @if (Model.FooterQuadFourth != null) {
                        <div class="@(HasText(footerQuadClass) ? footerQuadClass == "split-1" || footerQuadClass == "split-2" || footerQuadClass == "split-3" || footerQuadClass == "split-4" ? "span12" : footerQuadClass == "split-12" || footerQuadClass == "split-13" || footerQuadClass == "split-14" || footerQuadClass == "split-23" || footerQuadClass == "split-24" || footerQuadClass == "split-34" ? "span6" : footerQuadClass == "split-123" || footerQuadClass == "split-124" || footerQuadClass == "split-134" || footerQuadClass == "split-234" ? "span4" : "span3" : "")">
                            @Zone(Model.FooterQuadFourth)
                        </div>
                    }
                </div>
            }
        </div>
        <!-- end: Content -->
        @if (Model.AsideSecond != null) {
            <div id="sidebar-right" class="span3">
                @Zone(Model.AsideSecond)
            </div>
        }
    </div>
</div>
Jun 7, 2013 at 2:53 AM
Perfect! Same use case: different parts of the site /products, /services, etc. get their own menu. I'll give it a try after the long weekend.

Cheers,
- Steve


Jan 11, 2015 at 10:09 AM
I am using Orchard v.1.8.1.0 and creating a theme with Foundation. I am trying to follow this post, which makes perfect sense, I have created a SideMenu in navigation and added it to a widget layer in the AsideFirst zone. I have created Menu-SideMenu.cshtml, MenuItem-SideMenu.cshtml and MenuItemLink-SideMenu.cshtml. I have Menu.cshtml, MenuItem.cshtml and MenuItemLink.cshtml also under the Views folder of my theme. The side menu doesn't seem to take effect, it keeps rendering as the main menu.
Can someone direct me if I am missing something? or doing something wrong?

Regards,
Mario