Chapter 3. Displaying Content

As we saw in the previous chapter, getting a basic Orchard site up and running is a pretty low friction process. Without having to write a single line of code, we were able to create new pages with dynamic content and reasonably advanced functionality. However, we also saw that the content we displayed has a default rendering, which we can’t fully customize through the admin tools.

Fortunately, Orchard does provide functionality to allow us to alter this rendering. In fact, with minimal effort Orchard gives us great control over how we display content. Virtually every piece of data that gets rendered by Orchard (collectively known as shapes) may be customized by overriding its default template. In this chapter, we’ll learn about the conventions and tools that make this process relatively straightforward.

Customizing Biography Content

As it exists now, the bio projection page simply takes each field in our Bio content type and renders its label and value one after the other with each on its own line (see Figure 3-1). It would be better if our content read a little more naturally, such as “John Zablocki was born in Wethersfield, Connecticut, and plays guitar for Daisy’s Gone.” The label-value rendering might be sufficient for a product listing, but is less suited for our biography listing.

Ultimately, we’ll create a template for rendering Bio content items in a projection page (or any other container). However, to demonstrate how Orchard alternates work, we’ll start at a higher level and change the way all content is displayed when it’s rendered in a container (a projection in our case).

Orchard content is rendered differently based on its usage. For example, when content items such as those created from our Bio type are added to a projection page, their summary display type is used. When a full content item is rendered (i.e., an individual biography), then the detail display type is used.

The default bio projection page

Figure 3-1. The default bio projection page

Content Templates

If you open up the Themes project in your Orchard solution (in the “Themes” solution folder) you’ll find a directory named TheThemeMachine, which is the default Orchard theme. The styles associated with this theme are kept intentionally simple, because this theme is generally used as a starting point for building new themes. In the next chapter, we’ll create a new theme from scratch, but for now we’re going to work within this one.

The first thing to do is expand the Views directory. There you’ll see six Razor (.cshtml) files already in this folder. These files are all used by the “TheThemeMachine” theme. We won’t explore these files now as we’ll discuss them in the next chapter.

Add a file to this directory, named Content.Summary.cshtml. If you clear the contents of this new Razor file, save it and then refresh the “Bios” projection page, what you’ll see (Figure 3-2) is that the Bio item summaries have disappeared. Also notice that the “Upcoming Events” are no longer appearing in the projection widget that we added to the AsideSecond zone.

Note

The Themes project was not created using an ASP.NET MVC Visual Studio project template, therefore the usual MVC context menu shortcuts are absent from this project (i.e., “Add View”). Instead, I use AddNew Item and select “HTML Page” from the list of web templates. This action requires manually setting the .cshtml extension.

As you might suspect, Orchard found our new alternate template and used that file to render the summary display for our Bio items. You might also have realized that like our “Upcoming Events,” the Event and Blog Post items have also disappeared. You can verify this by clicking on the “Events” or “Blog” tabs. What this change is starting to demonstrate is how Orchard performs the task of “shape rendering.”

The effects of a blank Content.Summary.cshtml file

Figure 3-2. The effects of a blank Content.Summary.cshtml file

Alternate Templates

There are several file and directory naming conventions used by Orchard to determine which template should be used to render a particular piece of content. In our example, creating a view named Content.Summary instructed Orchard to use this template for all content shapes rendered with the summary display type. These views are known as “alternate templates.”

Again, content items in a projection page are rendered using the “summary” display type. We could edit our alternate template to add the header (title) and content (everything else) back in. To do so, we need to add only two lines of code. For illustrative purposes only, we’ll also change the background color of the content:

<div style="background-color:#c0c0c0;">
@Display(Model.Header)
@Display(Model.Content)
</div>

If you save the template and refresh the bio, event, and blog projection pages, you’ll see that the content is again being rendered as before, but now with a gray background. You’ll also see our “Upcoming Events” widget being rendered the same way.

To change this alternate template so that only Bio content items are affected by the customization, you simply have to rename the file to Content-Bio.Summary.cshtml. Orchard will parse the token after the hyphen and match it to a content type id. In this case “Bio” was the default content type id associated with the Bio content type when we created it. With this change, Event and Blog Post items are no longer rendered with a gray background within their respective containers.

You could also rename the file to Content-17.Summary.cshtml, where “17” is the unique identifier of a particular piece of content (my bio in my case). After renaming the file, if you refresh the “Bios” page you’ll see that only the bio summary specified in the filename has been grayed (Figure 3-3). This item level customization might be useful for calling out a particular item in a list, such as a special event.

A template for a single content item

Figure 3-3. A template for a single content item

Let’s rename our alternate template back to Content-Bio.Summary.cshtml so that we can return to our original goal, which was to render our bio listings with more natural language. To achieve this goal, we’re going to create a simple template that will display values from our content type in an order that we define.

Our template first defines a simple Razor function splitName for convenience. We’re going to take the shortcut of parsing our first name out of the title, as opposed to creating a separate field for this value in our type definition. We’ll then check whether a profile picture has been set. If it has, we’ll display it:

@{
    Func<string, string[]> splitName = (name) => name.Split(' '),
}
<div style="float:left;margin-bottom:10px;">

@{ var fileName = Model.ContentItem.Bio.Headshot.FileName;
   if (! string.IsNullOrEmpty(@fileName)) {
    <img src="@Url.Content(fileName)" alt="@Model.Title"
        style="float:left;margin-right:10px;" />
   }
}
<a href="@Model.ContentItem.AutoroutePart.DisplayAlias">
  @Model.ContentItem.TitlePart.Title
</a> plays
@Model.ContentItem.Bio.Instruments.Value.ToLower() for Daisy's Gone.
<p />
@splitName(Model.ContentItem.TitlePart.Title)[0] is originally from
@Model.ContentItem.Bio.Birthplace.Value and currently lives in
@Model.ContentItem.Bio.LivesIn.Value.
</div>

Next we display a link to the full bio page. We set the href property of the anchor tag by accessing the Bio content item’s Autoroute content part, which has the URL slug for permalinks. We then construct a sentence that summarizes a little information about each musician. In this sentence, we’ll access both the Bio type’s fields and its Title part to fill in the template values.

The important thing to note is that if you want to reference fields from a content item in your templates, you’ll need to use a dynamic expression that is generally of the form Model.ContentItem.{ContentType}.{FieldName}.Value. Other elements such as the title require first accessing its content part. Later on in this chapter, we’ll see how to discover these values using the Orchard tools.

We just fixed our bio summary templates so that the content wouldn’t just dump out labels and values for each property. However, when we click through to an individual bio, we can see that the detail view for our page looks like our summary did before our customization.

To get our bio details and summary views more in line, we’ll add a new alternate template. Start by creating a new Razor file named Content-Bio.cshtml in the Views directory in “TheThemeMachine.” This new template will be only a slight variation of the Bio item summary template we just created:

<h1>@Model.ContentItem.TitlePart.Title</h1>

@{ var fileName = Model.ContentItem.Bio.Headshot.FileName;
   if (!string.IsNullOrEmpty(fileName)) {
    <img src="@Url.Content(fileName)" alt="@Model.Title"
        style="float:left;margin-right:10px;" />
   }
}
Plays @Model.ContentItem.Bio.Instruments.Value.ToLower()
for Daisy's Gone.<p/>
Originally from
@Display(Model.ContentItem.Bio.Birthplace.Value).<p />
Currently lives
in @Model.ContentItem.Bio.LivesIn.Value.<p />
@Html.Raw(Model.ContentItem.BodyPart.Text)
The customized bio listing

Figure 3-4. The customized bio listing

It’s also worth noting that if we removed the summary alternate template, this new template would then be used to render summary listings as well since the name of this file doesn’t specify a display type (i.e., Summary or Detail). We could also have (and probably should have) named this file Content-Bio.Detail.cshtml to remove the potential impact on summary displays.

Note

Since shapes are dynamic types, it’s occasionally helpful to attach the Visual Studio debugger to your Orchard application to inspect the object being bound to your view. You can set a break point in a Razor file in a code block, which is any executable line between a @{ }.

Customizing Events

Like our bios in our bio listing, events in our events listing are rendered one property at a time with labels and values occupying one line each. Arguably, this display is appropriate for events, so we won’t create an alternate template for event summaries. However, we do want to adjust the order in which fields are rendering. Figure 3-5 shows that the location appears before the body field, while the event date is after. We’ll move both of these fields ahead of the HTML body field.

Default event listing

Figure 3-5. Default event listing

Placement Files

To rearrange the fields, we’ll use a special XML file named Placement.info that lives in the root of a template directory. This file defines rules for rendering content items, parts, and fields. “Place rules” allow module developers and template designers to provide preferred layout ordering for content pieces. We’ll modify the Placement.info file in the root directory of the “TheThemeMachine” theme by replacing its content entirely with this XML:

<Placement>
  <Match ContentType="Event">
    <Match DisplayType="Summary">
      <Place Fields_Text="Content:before">
      </Place>
      <Place Fields_DateTime="Content:before">
      </Place>
    </Match>
  </Match>
</Placement>

The Match element will limit the placement rule so that it affects only items of type Event that are shown with the summary display type. The Place rules that follow the Match specify that the text and date time fields will appear before the Content zone, where the HTML body is placed. If we want to force the event date to render after the location, we could provide relative numeric values instead of “before” or “after”:

<Place Fields_Text="Content:2" />
<Place Fields_DateTime="Content:3" />

Field Templates

We also want to jazz up our location field so that it renders a link to Bing Maps for that particular location. To do so, we’ll create an alternate template for just that field. This is different from what we did with Bio content, where the alternate template affected an entire item’s rendering.

Create a new directory named Fields under the Views directory in the “TheThemeMachine” theme. To that new directory, add a file named Common.Text-Event-Location.cshtml (prefixing this file with Fields would make the new directory unnecessary). The body of this new template will simply supply the value of our event’s location to the “q” parameter used by Bing Maps when it performs a search:

@Model.Name:
<a href="http://www.bing.com/maps/[email protected]">
  @Model.Value
</a><p />

If you refresh the event listing, you’ll now see the location field is wrapped in a link to Bing Maps. If you click through to view the actual event, you’ll see that the location field is also linking to Bing Maps (Figure 3-6). Our field alternate applies to both summary and detail displays.

The event location linking to Bing Maps

Figure 3-6. The event location linking to Bing Maps

There is still one last problem we want to fix. The ordering of the event fields in the details display type is not the way we want it. The event date is rendering below the content as was previously the case with event summary displays (Figure 3-6). To fix this, we’ll simply remove the Match tag from Placement.info where we’d previously restricted the display rule to summary only:

<Placement>
  <Match ContentType="Event">
      <Place Fields_DateTime="Content:1" />
      <Place Fields_Text="Content:2" />
  </Match>
</Placement>

Shape Tracing

While for some shapes it’s easy enough to figure out the correct naming for alternate templates based on the documented rules, it’s not always obvious. Fortunately, there’s the Shape Tracing module to help navigate the complex hierarchy of shapes that compose a page. Shape Tracing is installed but disabled when you create a site with the “Default” recipe. It can be enabled on the admin dashboard under ModulesFeatures. It’s listed under the “Designer” category.

After you enable the Shape Tracing module, across the bottom of each page of your site you’ll see a small bar with a small square icon all the way to the right. Clicking it will bring up the tools for outlining the shapes on a page.

Shape Tracing is a JavaScript-based utility that provides information about how zones and the shapes contained in these zones are rendered. As you move your mouse around the page, the Shape Tracing tool highlights content pieces such as zones, widgets, content parts, and fields.

The Shape Tracing developer tools

Figure 3-7. The Shape Tracing developer tools

Finding alternate templates

To demonstrate the utility of the Shape Tracing module, we’ll create an alternate template for the content of the “Body” field on our home page. We’re going to add an image to the content and float it to the left of the text. We could use the HTML editor to add an image, but this template will give us a little more control over layout.

With the Shape Tracing module activated (click the little square), mouse-over the Content zone. Click when one of the paragraphs is highlighted. The shape tracing console will display information under the “Shape” panel (Figure 3-7).

If you expand the “Alternate” tree under the “Shape” panel, you’ll see three possible options for creating an alternate template. Next to each option is a “Create” button that you can click to have the tool generate an alternate template for you in your current theme. Click “Create” to generate the Parts.Common.Body-11.cshtml. Recall that the number in the filename is the unique content ID of a content item and yours will vary.

Note

In order to navigate your site normally again, you must click the dash icon in the upper-right corner of the Shape Tracing tool, to turn off its functionality.

The Shape Tracing tool after clicking on a shape

Figure 3-8. The Shape Tracing tool after clicking on a shape

Note

If you use the Shape Tracing tool to create new alternate templates, these files won’t be added to the project automatically. You’ll need to click “Show All Files” in Visual Studio’s Solution Explorer to see them. You can then select “Include in Project” from the context menu.

After you click to create this new alternate template, back in the Views directory of the “TheThemeMachine” theme, you’ll find the new file. By default its code just renders the HTML property of the Model property of the page. The Shape Tracing module creates alternate templates based on current template for that piece of content.

Now we’ll add the new image for our home page. Create a new media folder by clicking MediaAdd a Folder. Name the new folder “Art” and click “Save.” Click into “Art” and then click “Add Media” and upload an image.

After it’s been uploaded, click the filename to get its path (copy the “Embed” value). Then back in Visual Studio, open Parts.Common.Body-11.cshtml and add an HTML img tag with the source set to this new image. We’ll render the saved HTML (which is simply the “Body” content) next to our Daisy’s Gone logo:

<img src="/Orchard/Media/Default/Art/daisyslogo.png"
     style="float:left;margin-right:10px;" />
@Model.Html

We also could have named the template Parts.Common.Body-Page.cshtml. This naming would have resulted in all pages with a Body part being affected. For our site, that would have meant the home, contact, gallery, and about pages would all include the new image. Even the “News and Notes” HTML widget would be affected.

The alternate Body template

Figure 3-9. The alternate Body template

Finding shape properties

The Shape Tracing module also provides us with a way to figure out object hierarchies for our template alternates. If you wondered how the expression Model.ContentItem.AutoroutePart.DisplayAlias was discovered for use in our bio templates, it was the Shape Tracing module.

Hover again over a piece of content while the Shape Tracing module is enabled, but this time click the “Model” tab in the console. You’ll see a tree (Figure 3-10) that contains information about the ContentItem property of the view’s Model property.

You’ll see details of content parts and fields. As you click through the tree, the expression to access these properties appears just below the tabs. Simply copy that expression into your alternate template. For example, you could highlight an event in our “Upcoming Events” widget and click through the model to find the location expression @Model.ContentItem.Event.Location.

The Shape Tracing module can also be used to see the placement rules for a piece of content, the current template used to display that content and the actual HTML rendered for that content. It’s an incredibly powerful tool to have at your disposal. You’ll use it frequently while customizing the display of content on your site. Just don’t forget to disable the module if you’ve enabled it on your live site for testing.

The Shape Tracing model panel

Figure 3-10. The Shape Tracing model panel

Summary

We’ve seen in this chapter that Orchard provides extensive ways to customize content. We can provide alternate renderings for full content items or individual fields within our content. Our alternates were somewhat utilitarian in that they offered improved and new functionality or changed the way something rendered. The second part of customizing content in Orchard is to create striking visual changes to the way content is rendered. We’ll learn how to make such changes in Chapter 4.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset