Content Type Template

Topics: Writing themes
May 26, 2011 at 7:43 AM

I have defined a 'Content Type' in the Admin panel called Staff, which has Name (text), Role (text),Bio (Html), and Photo (image) fields, with Parts including Containable and Common.

Created a list for Staff.  Added to a page.

Now how do I go about customizing the template for rendering a Staff item in the list?  I require a very specific layout.   I've reread the docs on placement.info and alternates.  I've looked at the shape tool.  it is still not coming together for me.... unless I cannot do this with a content type created in the admin panel? Do I need to create a module for this? 

It seems I'm missing a key concept, I've developed a couple of straight MVC3 sites, but orchard has me running is circles.

It's late and my brain is swimming in tree sap :)

Thanks, Brent

May 26, 2011 at 10:47 AM

It depends what you want to customize about that item. In placement you can use <Match ContentType="Staff" DisplayType="Summary"> to control placement for items in that list. Individual templates can be customized by creating an override called TemplateName-Staff.cshtml. In Shape Tracing expand the "Alternates" node and you'll see a list of override template names. Click the "Create" button and the template will be created for you in the active theme.

May 26, 2011 at 3:44 PM

I understand those concepts.  I've used shape tracing to generate an alternate, which basically outputs @Display(Model.Content) for the actual Staff details, relying on each of the fields to render themselves, which, as you said, can be overridden individually.  The placement I can control the order of the fields and meta data.  How do I control the interplay between the fields and meta data? 

Here is an example of what I wish to do, not a simple listing of the items, but control of the layout and flow of the text:

May 26, 2011 at 3:47 PM

Not sure what you're asking for ... you say you can control the placement of each field, and also override their templates, so what is it you can't do?

May 26, 2011 at 4:02 PM
Edited May 26, 2011 at 4:13 PM

eg, this was used to create the above image:

 

		<div id="staff_photo">
			<img src="images/staff_photo.jpg" alt="" width="115px" height="115px" />
		</div>
		<div id="staff_info">
			<h2>Chris XXXX</h2>
			<p><em>Head Trainer</em></p>
			<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. In ante enim, ...snip...</p>
		</div>

The staff_info div surrounds the name/role/Bio info, separate from the staff_photo div.  how do I get a div around a subset of the Model.Content?

May 26, 2011 at 4:06 PM

Hmmm... After doing this, perhaps I need to break out the staff_info into a separate Content Item?  can I compose a Content Item out of a field and another Content Item?

May 26, 2011 at 4:15 PM

For this you need to use Zones. You say you override the Content.cshtml so you only have a Content zone. What you need to do is add more zones so you have a Photo zone and a StaffInfo zone. Then use placement to put the right parts in the right zones. Then there'll be a zone div wrapper around them which you can use for styling.

May 26, 2011 at 4:27 PM

So I can create new Zones in my Content__Staff.cshtml? and how would I go about assigning the staff photo to one zone and the name/role/bio to another zone from the content item?

Sorry to seem so dense :0.  this is the last roadblock for me of understanding creating a theme/site in Orchard.  Appreciate your time helping me.

May 26, 2011 at 4:29 PM

Opps, re-read your last post and see you answered the placement issue.  Just need to confirm it is the Content__Staff.cshtml that I can put zones in?

May 26, 2011 at 6:17 PM

Content.cshtml has several zones already. That line you have that says @Display(Model.Content) - that's a zone right there. You can add as many zones as you like. They're slightly different to the layout zones but under the surface it's exactly the same thing. Placement controls which Content zone things go in, whereas Layers control which Layout zone widgets go in. Hope that makes sense :)

May 26, 2011 at 6:35 PM

Very good, thanks!  I am making great progress.  In my Content-Staff.cshtml I have these zones defined: 

 

    @Display(@Model.StaffPicture)
    @Display(@Model.StaffInfo)

 

In my placment.info, I have:

  <Match ContentType="Staff">
    <Match DisplayType="Summary">
      <Place Fields_Contrib_Image-StaffPicture="StaffPicture"/>
      <Place Fields_Common_Text-StaffName="StaffInfo:1"/>
      <Place Fields_Common_Text-StaffRole="StaffInfo:2"/>
      <Place Fields_Contrib_Html-StaffBio="StaffInfo:3"/>
    </Match>
  </Match>
This shows everything but the StaffBio field.  Any idea why the Html field does not show up?  Perhaps I should just change the StaffBio field to be a Body part.

May 26, 2011 at 8:24 PM

Not too sure about the HtmlField - but yeah you're probably better off just using body!

Jun 23, 2011 at 6:50 PM
Edited Jun 23, 2011 at 6:57 PM

This approach seems SUPER complicated!

Jun 23, 2011 at 7:08 PM

Um ... it actually makes things rather simple, especially further down the line when you want to add more stuff to existing areas. And you can use completely different view overrides based on all different kinds of situations. Care to elaborate what you think is complicated about this?

Coordinator
Jun 23, 2011 at 7:19 PM

Jonathon: you can always be super-explicit in your templates about what you display, but that means that if you ever need to add new parts, or if shapes get injected by a module somewhere, you will have to touch all the templates, everywhere, to take it into account. With placement files, you just add one line in one place. So you have a choice here. It's your call really. (thanks for the edit by the way).

Jun 23, 2011 at 8:45 PM
Edited Jun 23, 2011 at 8:50 PM

Right now I'm trying to write a tutorial, with an associated screen cast for a Indoor Climbing Gym marketing manager using WebMatrix to create a "Competitions" section on their website where they can add a date, poster (Img Field), photo gallery & comments.

I'm pretty sure I can get someone non-tetechnical to understand every step so far except how to rendering the items in the list and the detail version of the competition - I've been reading around the forum for over an hour and even I haven't figured it out straight away :(.

I'm happy to loose flexibility to achieve simplicity. The best solution so far I've seen is to add at "Content__Competition.cshtml" view, but not quite sure how to access each field for rendering - (really close though using this post as a guide - http://orchard.codeplex.com/discussions/256275 - just feel like there could have been better documentation as there are at least 10 threads trying to solve this problem. I might follow up with a blog post about options for solving the problem.

EDIT: I Think at the point where you are crafting a custom content type, the flexibility of placement seems as crazy as Asp .net 2.0 App_Theme and the ability to switch site UI based on user preference (hah, what mis-conception)

Coordinator
Jun 23, 2011 at 8:49 PM

http://weblogs.asp.net/bleroy/archive/2011/03/27/taking-over-list-rendering-in-orchard.aspx

Jun 23, 2011 at 8:54 PM
Edited Jun 23, 2011 at 9:05 PM

Sure... I get that with blogs:

http://www.kresner.com/jonathons-orchard-cms-blog/orchard-cms-taking-full-control-of-blog-rendering

But your example targets a content part... I'm just a bit slow trying to figure out how to do that for a custom content type... I'm probably close.

EDIT: THE 2 things I'm missing is:

1) How can I target a different template for Summary and Detail the documentation (http://orchardproject.net/docs/Accessing-and-rendering-shapes.ashx) only gives a Shape example for Content__[ContentType] which gets picked up by both Summary and Detail

2) How do I access my fields in the template e.g. the "Poster" field which is a url that I want to render as an image. Why doesn't Model.Poster render anything, or Model.Fields.Poster...

Coordinator
Jun 23, 2011 at 9:21 PM

This might give you some additional info then: http://weblogs.asp.net/bleroy/archive/2011/05/23/orchard-list-customization-first-item-template.aspx

Jun 23, 2011 at 9:31 PM
Edited Jun 23, 2011 at 9:48 PM

What I'm really hoping for, is a way that someone non-technical who has a grasp of html, with some small additional instruction via screencast / tutorial can take control of how something renders.

This is one of those moments where I think asp .net mvc is simple and this can be achieved in 5 seconds, but with Orchard I'm banging my head against the wall for more than an hour.

I'm really hoping for something synonymous with normal asp .net mvc view/model with an override convention in the file name targeted to a specific content type.

I might be missing something very basic, but I do not want to ask my clients to learn C# or shape alternates!

What I would like is for an author in WebMatrix to create a View   Content__Competition_Summary.cshtml and render how they like for example:

<div>@Model.Title</div>

<img src="@Model.Poster" />

or even better

<div>@Field.Title</div>

<img src="@Field.Poster" />

Coordinator
Jun 23, 2011 at 10:48 PM

Which is why I sent articles giving explanations so that someone who want to build such a tutorial can.

On the other hand, I don't understand what you are asking. What do you call that Content__Competition_Summary.cshtml that you are calling for? Isn't that exactly, precisely an alternate? I thought you didn't want your customers to have to learn about those? Which is it?

Jun 24, 2011 at 12:06 AM

Getting closer. Let's clarify.

- I don't want content authors to have to install the designer tool and know what shape alternates are as described in your blog "Alternates are a collection of strings that describe additional shape names for the current shape. That list of strings lives in the Metadata.Alternates property of any shape:"

- I don't want them to code a shape in C# with the [Shape] attribute and know how to hook it up with an event handler.

1) I want to know if there is a convention to target the detail & summary templates for a specific custom content type. It was not occurring to me from the Naming Shapes and Templates Accessing and Rendering documentation because I was focusing on the first item with Content__[ContentType]. I'm still not sure what the difference between [ContentType] and [DisplayType] is, but what I have finally figured out via playing with the shape tracing tool, is that there is a convention (which I was trying to ask if/what it was...).

It is as follows:

Content-{ContentTypeName}.Detail.cshtml        (in my case Content-Competition.Detail.cshtml)

Content-{ContentTypeName}.Summary.cshtml   (in my case Content-Competition.Summary.cshtml)

2) Now that I can target the content type/view I want, how do I access/ render the value of any given field? I do not see anything in either of your posts that give an example of how to render a field.

These don't work for me:

@Model.{FieldName}

@Display(Model.FieldName)

Coordinator
Jun 24, 2011 at 12:14 AM

Again the shape tracing tool tells you that. It's useful. Here's what it's telling me for a MyField field that I added to a page:

@Model.ContentItem.Page.MyField.Value

Jun 24, 2011 at 12:24 AM

Yes thank you, I'm not sure where the shape tracing tool points that out... Feel free to make it clearer, but now I've inferred that you can render any field with the following:

@Model.ContentItem.{ContentTypeName}.{FieldName}.Value

 

Would it be out of line to ask for simpler syntax that I could advise clients to use, such as @Field.{FieldName} or @Data.{FieldName} ?

Coordinator
Jun 24, 2011 at 12:27 AM

In the Model tab. If you want to add a helper to make that shorter, you can very well do so.

Jul 18, 2011 at 2:31 PM
techwest wrote:

Very good, thanks!  I am making great progress.  In my Content-Staff.cshtml I have these zones defined: 

 

    @Display(@Model.StaffPicture)
    @Display(@Model.StaffInfo)

 

In my placment.info, I have:

 

  <Match ContentType="Staff">
    <Match DisplayType="Summary">
      <Place Fields_Contrib_Image-StaffPicture="StaffPicture"/>
      <Place Fields_Common_Text-StaffName="StaffInfo:1"/>
      <Place Fields_Common_Text-StaffRole="StaffInfo:2"/>
      <Place Fields_Contrib_Html-StaffBio="StaffInfo:3"/>
    </Match>
  </Match>
This shows everything but the StaffBio field.  Any idea why the Html field does not show up?  Perhaps I should just change the StaffBio field to be a Body part.

 

Could you show the template, I dont know how to add zone to Content-Staff.cshtml

 

Aug 2, 2011 at 6:53 PM

This has been an informative thread. I'm coming from an MVC background as well and Orchard's use of placement, shapes, alternates, etc. is a bit overwhelming. Orchard's concept count is very high and unfortunately, doing simple things like customizing the displaying of content just isn't simple, or doesn't appear to be. Part of the issue Orchard is facing is that many people that are using it and trying to customize it have an MVC background, where it's quite simple to select a layout and template content. In Orchard, I feel like I have to touch too many parts just to change how a custom content type is displayed in a given scenario.

Coordinator
Aug 2, 2011 at 7:08 PM

Everything you do in MVC you can do in Orchard. Then again, if you need the additional flexibility of the content type system, there is a cost. If placement is too much, you can actually do without it, and I wrote a post explaining how: http://weblogs.asp.net/bleroy/archive/2011/07/31/so-you-don-t-want-to-use-placement-info.aspx

Mar 18, 2012 at 5:28 AM
Edited Mar 18, 2012 at 11:40 AM
techwest wrote:

Very good, thanks!  I am making great progress.  In my Content-Staff.cshtml I have these zones defined: 

 

    @Display(@Model.StaffPicture)
    @Display(@Model.StaffInfo)

 

In my placment.info, I have:

 

  <Match ContentType="Staff">
    <Match DisplayType="Summary">
      <Place Fields_Contrib_Image-StaffPicture="StaffPicture"/>
      <Place Fields_Common_Text-StaffName="StaffInfo:1"/>
      <Place Fields_Common_Text-StaffRole="StaffInfo:2"/>
      <Place Fields_Contrib_Html-StaffBio="StaffInfo:3"/>
    </Match>
  </Match>
This shows everything but the StaffBio field.  Any idea why the Html field does not show up?  Perhaps I should just change the StaffBio field to be a Body part.

 

Hey guys, I'm trying to recreate this exact scenario but i'm so far failing.  Am I to undertsand the two zones 'staffpicture' and 'staffinfo' should wrap a div around their contents of the same zone name upon rendering...Or, won’t I have to add some code to the layout [or wedge it in content or the likes] something like:

@if (Model.StaffPicture!= null) {
    <div id="StaffPicture">
        @Zone(Model.StaffPicture)
    </div>
    }

Thanks for any pointers or some documentation to assist me in recreating the above, cheers dyrgutt

Developer
Mar 18, 2012 at 6:41 PM

The only thing required to render a local zone called "StaffPicture" is calling @Display(Model.StaffPicture) from within your content item template. So if you defined a content type called "Staff" and attached the mentioned fields, any content item of that type can be rendered using a template called "Content-Staff.cshtml", in which you can render any local zone that you can think of. Any shape that is defined in the Placement.info file and is assigned to the zone name you came up with, will be rendered in that zone. Check out the following post that explains this in more detail: http://weblogs.asp.net/bleroy/archive/2011/06/30/so-what-are-zones-really.aspx

Mar 18, 2012 at 10:26 PM
Edited Mar 18, 2012 at 10:33 PM

Thanks for the reply sfmskywalker...Ok, i'm still being slightly daft? Here is what I have:

placement.info

 

  <Match ContentType="BoardMember">
    <Match DisplayType="Summary">
      <Place Fields_Contrib_Image-MemberPic="BoardMemberPic"/>
      <Place Fields_Common_Text-Credits="-"/>
      <Place Fields_Common_Text-Position="BoardMemberInfo:2"/>
      <Place Fields_Common_Text-Main="BoardMemberInfo:3"/>
    </Match>
  </Match>

 

Content-BoardMember.Summary.cshtml

 

@Display(Model.BoardMemberPic)
@Display(Model.BoardMemberInfo)

 

Which when rendered contains the following HTML:

 

<div class="group" id="content">
    <div class="zone zone-content">
        <article class="content-item projection-page">
    <header>
        
<h1>Board Members</h1>
    </header>
    <ul><li class="first">

<p class="image-field">
   
  <img width="150" height="193" alt="" src="/OrchardLocal/Media/Default/Content/Images/Members/0-1.jpg">
</p>


    <p class="text-field"><span class="name">Position:</span> <span class="value">Financial Advisor</span></p>

    <p class="text-field"><span class="name">Main:</span> <span class="value"></span></p><p>Tom has had a long and successful career ...</p><p></p>
</li><li>

<p class="image-field">
   
  <img width="150" height="193" alt="" src="/OrchardLocal/Media/Default/Content/Images/Members/2-1.jpg">
</p>


    <p class="text-field"><span class="name">Position:</span> <span class="value">Fundraising Coordinator</span></p>

    <p class="text-field"><span class="name">Main:</span> <span class="value"></span></p><p>Terry has been very ...</p><p></p>
</li><li>

<p class="image-field">
   
  <img width="150" height="193" alt="" src="/OrchardLocal/Media/Default/Content/Images/Members/3-1.jpg">
</p>


    <p class="text-field"><span class="name">Position:</span> <span class="value">Health Advisor</span></p>

    <p class="text-field"><span class="name">Main:</span> <span class="value"></span></p><p>Kylie jumped at the ...</p><p></p>
</li><li class="last">

<p class="image-field">
   
  <img width="150" height="193" alt="" src="/OrchardLocal/Media/Default/Content/Images/Members/4-1.jpg">
</p>


    <p class="text-field"><span class="name">Position:</span> <span class="value">Project Management</span></p>

    <p class="text-field"><span class="name">Main:</span> <span class="value"></span></p><p>Sian never wanted to see ...</p><p></p>
</li></ul>


</article>
    </div>
</div>

 

So, what I was expecting to see within the <li>'s was the action zone's as divs, something like:

 

<li class="first">
    <div id="BoardMemberPic">
        <p class="image-field">
            <img width="150" height="193" alt="" src="/OrchardLocal/Media/Default/Content/Images/Members/0-1.jpg">
        </p>
    </div>
    <div id="BoardMemberInfo">
        <p class="text-field">
            <span class="name">Position:</span> <span class="value">Financial Advisor</span></p>
        <p class="text-field">
            <span class="name">Main:</span> <span class="value"></span>
        </p>
        <p>
            Tom has had a long and successful career ...</p>
        <p>
        </p>
    </div>
</li>

So, am I still clearly not grasping the zone concept, or am I going about it slightly wrong? Do I have to manually place the div tags around my zones in the content-boardmember.summary view e.g.:

<div id="local-board-member-pic" class="zone">
    <div id="zone-board-member-pic">
        @Display(Model.BoardMemberPic)
    </div>
</div>
<div id="local-board-member-info" class="zone">
    <div id="zone-board-member-info">
        @Display(Model.BoardMemberInfo)
    </div>
</div>
???

Thanks for any help guys. Cheers Dyrgutt

Developer
Mar 19, 2012 at 12:52 AM
Edited Mar 19, 2012 at 12:54 AM

Now I see what you mean! Well, I haven't played around with Zone templates yet, but in any case you could just manually place the div tags around your zones as per your example. That should simply work (although I wouldn't recommend using the "id" attribute with the hardcoded values, as id's are meant to be unique on a page).

What would be interesting to try out is whether you can achieve the same effect by using Zone temlates, which I assume will act as wrappers around your actual zone shapes. I remember seeing a Zones folder in one of the modules (within the Views folder).

I imagine that you could create a zone template named "BoardMemberPic.cshtml" in the Zones folder, which would contain markup like this:

<div id="local-board-member-pic" class="zone">
    <div id="zone-board-member-pic">
        @Display(Model.Content)
    </div>
</div>

Then in your content template, you would just have to call @Display(Model.BoardMemberPic) (without manually wrapping the <div> elements around it, as that would have been handled by the zone template.

Again, I don't know if it works like that, but do let me know when you find out :)