Orchard CMS ContentShapes - can I add a wrapper? - orchardcms

I have a resource in OrchardCMS that I'm displaying through a number of smaller shapes (so that I can adjust the layout order in placement.info).
In the Driver I am returning these parts through the use of returning a Combined(ContentShape(...), ContentShape(...), ContentShape(...)) etc
However I would like the HTML of each of the smaller shapes to appear within an HTML wrapper (such as a div or article or suchlike)
How do I go about doing this?
Thanks

I understand what you are trying to achieve but it isn't really a feasible scenario. A wrapper is applied to a shape and combined returns several shapes. As you say, each shape has an entry in the placement.info file, so you could easily have these shapes within different content zones or zones spread around your page, where a wrapper would just not work. Make sense?
The answer is probably that you need to create an override for the content view of the content type you are displaying and add the stuff you want to put in your wrapper in there. e.g. if your content type is called MyType and the displayed type was detail, your view would be called Content-MyType.Detail.cshtml.

Do you mean an Orchard wrapper (whole new cshtml file), or just a HTML element?
In the latter case you can do in your part view:
#{
var tag = Tag(Model, "article");
}
#tag.StartElement
stuff
#tag.EndElement
If you want to wrap a (common) wrapper around your elements, you can do the following in your placement.info:
<Place Parts_MyPart="Content:1;Wrapper=MyWrapper" />
<Place Parts_MyOtherPart="Content:2;Wrapper=MyWrapper" />
And create a MyWrapper.cshtml:
<article>
#Display(Model.Child)
</article>

Related

Is it possible to render a part twice in one display type? - Orchard CMS

I have a content type, Events, that has a part "StartDate" that I need to show twice in the summary view. Is it possible inside placement.info to render the part in "this" zone AND "that" zone?
Render the zone twice
Probably not through just using the placement.info file but if you edit the .cshtml view you can just render a zone twice.
For a test I just edited my blog detail view to have this code:
#Display(Model.Content)
#Display(Model.Content)
It worked, and displayed it twice. It's something you should probably be careful with this as in that example it rendered out my Disqus comments twice which created a clash because the same id was used twice on a single page.
Fine tune it with Part Relocation
If you need to pull a single bit of content (a shape/part) out of an existing zone you can also do it with something called Part Relocation which is explained in this Orchard Harvest Session.
The basic idea is to use placement to isolate it into its own zone:
<Match ContentType="News" DisplayType="Detail">
<Place Parts_StartDate="MakeUpAZoneName" />
</Match>
(Note: the Match tag is just an example, its the Place you will need to put in whatever match you want)
And then you can render that out in your .cshtml file with #Display() like:
#Display(Model.MakeUpAZoneName)
... other html code ...
#Display(Model.MakeUpAZoneName)
You can't render same shape twice, but simply you can return combined shapes from your driver and render each shape in different zone.
No its not possible, Only the first one in the file placement.info works.

Overriding Widget View in Orchard

I setup a custom content definition, query and projection inside Orchard (1.8) and just about everything with it works great, including overriding the display view on the projection page's URL. The only issue I'm running into is when I put that same projection in a widget, I can't seem to figure out how to override the view for it. The automatically generated HTML is this:
<p class="text-field"><span class="name">Name:</span> <span class="value">/** Title from content item **/</span></p>
<p>more</p>
<p>asdfasdfasdrerfwerqaq324f421 more</p>
<p class="date-time-field date-time-field-date">
<span class="name">Date:</span>
<span class="value">/** Date from content item **/ </span>
</p>
I've tried using the Shape tracer to create an alternate view, but even when I only have #Display(Model.Content) in the new view, it still puts all of that extra stuff in it which is more than I need to show on this view. The shape tracer says the active template is my new one with only that value in it, so I'm not sure where all the extra HTML is coming from here (though it does show on the HTML tab of the Shape tracer).
How can I override the view for this widget?
If the extra HTML is only appearing when you post the projection as a widget it is probably due to wrapper tags added through code or through the widget wrapper template. Try either of these methods:
Check Widget.Wrapper.cshtml to see if that view template contain the extra HTML. I don't remember if this shape shows up in the shape tracer, it might show up under the wrappers section.
You can also try the trick below - this can remove unwanted markup in some cases, I use it for the menu navigation widget. It removes any wrappers that were added through code. Make your widget template look like this:
#Display(Model.Content)
#{
Model.Metadata.Wrappers.Clear();
}

Use alternate shape template for content inside Projection

I have a simple Content Type, let's say BlogPost. I want a widget "Recent blog posts". I know it exists as out of the box widget for Blog Posts. But we are imagining a generic Content Type here in place of Blog Post. I want to create it as a Projection Widget.
I made a Query, created projection widget, named it "Latest Blog Posts", and it works fine.
Now I would like to specify exact template that each of the blog posts in that projection list should use when displaying.
Currently, here are my options for shape alternates in this situation:
So, in the left pane:
Widget is a Projection Widget I created. It uses a Query on Blog Post content types with grid layout. Each of the "Content" items in the left pane represent one of the Blog Post that the projection is showing.
Now, for example, I would like each of the Blog Posts to be shown in a short variant. I don't want to override BlogPost.Summary shape template since I may need that shape somewhere else on the site.
In the right pane I have all of the available alternates for a single Blog Post shape inside a projection widget.
Ideally, I would like to have an alternate shape template called something like:
"~/Themes/Bootstrap/Views/Content-BlogPost.Summary.LatestBlogPosts.cshtml"
After that I would go for:
"~/Themes/Bootstrap/Views/Content-BlogPost.Summary.ProjectionWidget.cshtml"
Or anything of that kind in order to have special shape template for showing a blog post inside a projection widget.
My alternative approach was using the Placement.info file. I wanted to hide certain parts of a BlogPost:
<Match ContentType="ProjectionWidget">
<Place ShapeParts_Common_Metadata_Summary="-" />
<Place Parts_Tags_ShowTags="-" />
<Place Parts_Common_Body_Summary="-" />
</Match>
This segment does nothing. I haven't been able to make it work yet.
So, I hope I made my problem clear. I want to be able to specify the exact look of a Blog Post when it is showing in a Projection Widget. How can I do this?
It's way easier to change the display type.

Advanced Orchard Theming - Object Model vs Placement.info?

I have been tasked with converting a design heavy, fairly advanced HTML template for a site into an Orchard theme and I am struggling with the best way to accomplish certain things. The theme is built on bootstrap and is a modern responsive HTML template like you might find on ThemeForest or something. The site will have a number of content types (staff members, portfolio items, partners, etc.) and will need a number of templates. The content types will have a large number of fields (upwards of a dozen) inside of custom content parts.
Based on what I have read the proper way to do theming in Orchard is using placement.info in combination with alternates, wrappers, etc. This gracefully handles if parts or properties are added/removed. However, this technique is quickly becoming overwhelming, since I have to declare the name and order of every field/part in the placement.info for every content type, and every display type of that content type. Each field of each content type then needs to be wrapped in very specific html. This creates an issue because a single page can be split out into potentially a couple dozen views, with HTML tags opening in one view and closing in another.
The best work around for this I have found is to basically ignore the placement.info file and build templates just by traversing the object model. So basically, for a portfolio page, I would copy in the template HTML I have and then replace the text values with values from the model. This might look something like:
<li class="#Display(Model.ContentItem.PortfolioPart.PortfolioCore.Value.ToLower())">
<a href="#Url.ItemDisplayUrl(contentItem)" >
#foreach (var media in Model.ContentItem.PortfolioPart.PortfolioImage.MediaParts)
{
<img src="#Display(media.MediaUrl)" />
}
<span class="type">#Display(Model.ContentItem.PortfolioPart.PortfolioCoreArea.Value)</span>
<span class="portfolio-item-content">
<span class="header">#Display(Model.ContentItem.TitlePart.Title)</span>
<span class="body">
<p>
#Display(Model.ContentItem.PortfolioPart.PortfolioTagline.Value)
</p>
</span>
</span>
</a>
</li>
The benefit with this method is that I can apply all of the values in a couple of views and it's more readable. Obviously the problem with this is that if any properties or parts are removed, the template breaks.
Is there a way in Orchard to have the best of both worlds? I can't have a wrapper or template for every field - this would end up potentially hundreds of fields by the end. I also might need to display content types in multiple places with different views - each field would then require a whole new set of wrappers or alternates for every projection.
Please let me know if I'm missing anything or if there is a better way to do this besides manually traversing to the properties I need. I need a way to be able to easily plug in properties into very specific html.
My final thought was to use very specific templates for custom content types using the object model but still provide good general templates/placement.info file so that general Orchard content is flexible but the custom content types have to stay how they are.
Side thought - I guess another option would be to wrap any code that accesses a property directly in a try catch block or some kind of error handler helper, but that doesn't seem like a "best practice".
I think the techniques in this article are what you're looking for: http://weblogs.asp.net/bleroy/archive/2013/02/13/easy-content-templates-for-orchard-take-2.aspx

Orchard CMS: Add a stylesheet to a page

Setup:
I am using Orchard CMS 1.6.
I have a site where I need to be able to set the background color of the whole page. Ie, I need to style the body tag.
I could use the LayoutSelector module and have distinct layouts. However, the only difference in each layout is that the background-color rule for the body tag is different. So it seems a very un-dry way of doing things.
I can't find any way to make Vandelay.Classy add a distinct id or class to the body tag (it adds, as I understand it) an id or a class to the outer tag of a content type. In my case, that isn't the body tag.
So that is no good, I really do need to customize the body tag.
How to do this?
Note:
I need 3 different background colors. I also have a two column layout and a three column layout. [I use (a modified version of) the layoutSelector module to achieve this.] So to have 3 different colors of background, and I used layouts to achieve this, I would need 6 different layouts: TOTAL overkill.
There must be a better way...
From any cshtml file, you should be able to access the Layout shape. From pretty much anywhere else, you can still get to the Layout shape through WorkContextAccessor. Once you have a reference to the Layout shape, you can do Layout.Classes.Add("the-class-you-want").

Resources