Can I create a shape from within a view?

Topics: Customizing Orchard, General, Writing modules
Feb 15, 2012 at 12:25 PM

I have a custom controller and I am rendering a custom layout for a content type that contains several parts. I want to have total control over where each part is rendered within my markup. But as far as some of the parts themselves go, I want to use the layout that the parts already have defined. So far I have only figured out how to do this by building the shapes for each part inside the controller using var myShape1 = IContentManager.BuildDisplay(), and then calling @Display(Model.myShape1) in the template. 

Feb 15, 2012 at 12:40 PM

The default way to go is using Placement, but you could override the Content.cshtml shape and define new local zones (Model.ZoneName()) where you can push your shapes with Placement to.

What exactly do you want to achieve? If you want to display parts outsides the Content shape, Placement won't work, you've to either push shapes to the Layout directly or use randompete's cool Placement extension he wrote a blog post about.

Feb 15, 2012 at 1:58 PM

Well i achieved what I wanted but it seemed messy to have to build the shapes in the controller and then pass them to the template. If the model has references to the content parts already, I'd like to just render the sub parts from the view without having to build the shape from the controller. 

Does that make sense? 


Right now I do it like this (pseudo code, off the top of my head):


var part = _contentManager.Query<...>("MyPart").Where(..).List().FirstOrDefault(); 

var subPart = part.ContentItem.Parts.OfType<SubPart>().FirstOrDefault(); 

dynamic subShape = _contentManager.BuildDisplay(subPart, "Detail"); 

dynamic mainShape = _orchardServices.New.TopicPage(TopicPart: part, SubPartShape:subShape)

return new ShapeResult(this, mainShape)


and the TopicPage.cshtml view does this to render subPart :



I want to know if I can do something simpler, like: 


var part = _contentManager.Query<...>("MyPart").Where(..).List().FirstOrDefault(); 

dynamic mainShape = _orchardServices.New.TopicPage(TopicPart: part, SubPartShape:subShape)

return new ShapeResult(this, mainShape)



@Display(BuildDisplay(Model.ContentItem.SubPart, "Detail"))

Feb 15, 2012 at 5:29 PM

On a side note AFAIK what you call SubPart is just another part (you can "cast" parts just as content items, since they're both IContents), so it doesn't have a hierarchical relation with MyPart.

You could use the ContentManager also in views (by resolving it from WorkContext) and build the shape there, but this is a bit awkward. I think using a view model that stores both shapes (and parts, if you need them in TopicPage.cshtml) would be the nicest solution.

Feb 15, 2012 at 6:25 PM

Try this:

Also useful to know: @Display.Foo(bar: 42) will create a shape named Foo, with a dynamic model with a property bar containing 42. You can render that with a foo.cshtml template.