RenderSection in Orchard

Topics: Writing modules
Dec 1, 2011 at 8:42 AM

Hi, I need to add some markup from my module to the masterpage, when I used just ASP.NET MVC I did it that way:

@RenderSection("PopupsContent", false)
and
@section PopupsContent{
//content for masterPage
}

What should I use in Orchard for this purposes?

Coordinator
Dec 1, 2011 at 9:05 AM

The closest equivalent of master pages in Orchard is the Layout, of which there can be alternates.

The best way in general in Orchard (although RenderPartial is also available) to inject rendering is to create a shape on the fly: @Display.PopupsContent(MyFlag: false). The system will look for a template named PopupsContent.cshtml in your theme, and render it. Inside of that template, you can access your flag this way: @Model.MyFlag.

Dec 1, 2011 at 9:41 AM
Edited Dec 1, 2011 at 9:43 AM

what if my view (for inject to Layout) is closely connected to module (not the theme)?

Dec 1, 2011 at 4:36 PM

jalaz_VS: I think you need to explain a bit more about your situation, I'm not sure what you mean by "closely connected to module (not the theme)".

However, regarding your original question, Orchard's layout has "zones" and you can push stuff into these from anywhere. So you can do:

@Layout.PopupsContent.Add(Display.MyPopupShape())

Assuming you've created a PopupsContent zone in Layout.cshtml, and also defined Views/MyPopupShape.cshtml which is the shape getting pushing into there.

Dec 1, 2011 at 5:04 PM

On my site I have block for pop ups, that's located in the end of page.

But this block working only with one widget, so I needed to insert this block to Layout when module was enabled (that's why I wrote that it was closely connected to module (not the theme) :) ).

So, randompete, you've gave me right advice without whole understanding of situation :) it's awesome, thank you!

Dec 1, 2011 at 5:10 PM

Ok, I see. You can actually run the code from anywhere in your module if you inject IWorkContextAccessor and IShapeFactory.

dynamic shape = _shapeFactory;

_workContextAccessor.GetContext().Layout.PopupsContent.Add(shape.MyPopupShape());

However; this is a very manual way of doing things. Why don't widgets work for you? They are doing exactly the same thing, pushing shapes into layout zones; you can even have widgets appear in your new PopupsContent zone. So why not just expose a widget from your module, and then you can configure in the admin any zone for it that you like, with custom layer rules if you need to control when it shows.

Dec 1, 2011 at 7:09 PM

Yeah, I've just added PopupsZone to the end of page, and using @Layout.PopupsZone.Add(Display.PopUps()) in my widget, thank you for making clearance.

Dec 1, 2011 at 7:31 PM

My point is that when you create a widget (in admin) you specify which zone it goes into. So you can just add the widget to whatever layer and specify "PopupsZone" as the target zone - no need to push the shape to layout yourself.

Dec 2, 2011 at 8:26 AM

So if I have one widget in the middle of page and pupups block for this widget in the end of page, therefore I must to create two widgets (and put them in Sidebar and Popup zones), right?

Dec 2, 2011 at 3:24 PM

That's right. You can do it all from the admin pages, you shouldn't need to write any positional code.

Dec 2, 2011 at 4:17 PM

First off it seemed as complex thing for admin because:

1) He always must to keep in mind dependencies between two widgets.

2) In this case it's not necessary cause pupUps block always in the end of page.

 

But if to look from positional perspective it's very useful because it don't require to go in code for changes. Thank you, Pete!

Jul 2, 2014 at 11:25 AM
Edited Jul 2, 2014 at 11:27 AM
In Orchard version 1.8 ( I am not sure about the previous versions ) there is a code in ViewPage :
 public IDisposable Capture(Action<IHtmlString> callback) {
            return new CaptureScope(this, callback);
        }

        public IDisposable Capture(dynamic zone, string position = null) {
            return new CaptureScope(this, html => zone.Add(html, position));
        }
And you can use it as follows:
@using (CaptureScope(Layout.YourZoneName)) 
{
any razor code here
}
You have to use the using pattern because actually the shape is added to the zone when you dispose the returned object.

As Orchard is open source, you can also edit the source code to add another version of this method with a more clear name:
public IDisposable RenderIntoZone(dynamic zone, string position = null) {
            return new CaptureScope(this, html => zone.Add(html, position));
        }