Iteration in shape templates

Topics: Customizing Orchard, General
Apr 18, 2011 at 11:57 AM

Hi guys,

I'm very new to Orchard, and @Razor in general and need to extend the existing menu with a unique set of CSS classes.

I have identified where to find the template for the menu, Menu.cshtml and MenuItem.cshtml but need to determine how many items are in the collection, and add a new class depended of whether it's the last or first item in the collection. I've searched online for similar posts but could not find anything concrete, I can add classes and attributes using Model.Attributes.Add("") and Model.Classes.Add("").

Is there any way that I can create an iterator within MenuItem.cshtml, where I need to add the class rules, I've tried the following:

@{
    // odd formatting in this file is to cause more attractive results in the output.
    var items = (IEnumerable<dynamic>)Enumerable.Cast<dynamic>(Model);

    string[] colors = new string[] { "yellow", "blue", "pink", "orange", "lblue", "purple" };
    var count = 1;
}
@{
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 ((!string.IsNullOrEmpty(modelUrl) && requestUrl.StartsWith(modelUrl)) || requestUrl == modelUrl) {        
	    Model.Classes.Add("active");        
    }    
    
    // add necessary element styles
    Model.Classes.Add(string.Format("parent item{0} {1}", count, colors[count - 1]));

    if (count == 1) {
        Model.Attributes.Add("id", "current");
        Model.Classes.Add("first");
    }        
    
    var tag = Tag(Model, "li");
    @tag.StartElement
    <a href="@Model.Href"><span>@Model.Text</span></a>
    if (items.Any()) {
        <ul>
        @DisplayChildren(Model)
        </ul>
    }
    @tag.EndElement
    count++;
    }    
}

In green, is what I'm trying to achieve.

Thanks for the assistance in advance.

Regards,

Eric

Apr 18, 2011 at 12:57 PM

The DisplayChildren function (in WebViewPage.cs) just looks like this:

        public IHtmlString DisplayChildren(dynamic shape) {
            var writer = new HtmlStringWriter();
            foreach (var item in shape) {
                writer.Write(Display(item));
            }
            return writer;
        }

So in your above example, you'd replace the @DisplayChildren(Model) line with this:

@foreach (var item in items) {
    if (count == 1) item.Classes.Add("first");
    @Display(item);
    count++;
}

Apr 18, 2011 at 12:59 PM

Thank you randompete.