Easy content templates for Orchard, take 2
Placement.info is an XML file that orchestrates the different parts of a content item and sends each of the shapes they create into specific local content zones. If the previous sentence sounded confusing to you, fear not, this post is for you.
When writing an Orchard theme, more often than not, you know exactly what parts exist in your content type, and you know where you want them to render. Placement can be extremely powerful, but it’s rather abstract and it reverses the usual logic of placing contents on a page. What most people really want to do is write a template with simple markup and placeholders inside that markup for the rendering of specific parts such as title, summary, tags, etc. Placement forces you to dispatch those part shapes from a completely separate file.
In the Summer of 2011, I wrote a little article to explain how to write custom templates for specific content types in Orchard, without using placement.info:
So you don’t want to use placement.info?
The solution worked, but relied on a hack that will break with the next version of Orchard (1.7).
Sébastien Ros gave me a little trick the other day that enables the same thing, in a simpler, less hacky form. It still uses placement somewhat, but in a very simple way.
The idea is to create one local zone per part instead of the usual header, content and footer zones. Here we are going to send the relevant shapes to those zones through placement:
<Match ContentType="BlogPost"> <Match DisplayType="Summary"> <Place Parts_Common_Body_Summary="Summary:0" Parts_Tags_ShowTags="Tags:0" Parts_Common_Metadata_Summary="MetadataSummary:0" Parts_Comments_Count="CommentsCount:0" /> </Match> </Match>
This sends shapes into Summary, Tags, MetadataSummary and CommentsCount zones. Those do not yet exist.
Caveat: when naming your custom zones, be careful not to collide with existing properties or zones on the Model, lest you end up with unexpected and confusing results. Using longish and very explicit names usually works well for that.
The template can now simply create and render those zones. Here is my Content-BlogPost.Summary.cshtml template:
@using Orchard.ContentManagement @{ var blogPost = Model.ContentItem; } <article class="content-item blog-post"> <header><h1><a href="@Url.ItemDisplayUrl((IContent)blogPost)">
@blogPost.TitlePart.Title
</a></h1></header> @Display(Model.Summary) <footer> @Display(Model.Tags) @Display(Model.MetadataSummary) @Display(Model.CommentsCount) </footer> </article>
Notice how in the case of the title, I’m not even using the shape given by the part, but I’m accessing the properties directly on the TitlePart. The other parts are rendered through the special zone that we created using the Display function. And that is all. You can now focus on building your template, and it will be pretty obvious what will render where…