Rendering a part as part of the module

Topics: Customizing Orchard, General, Writing modules
May 30, 2011 at 4:32 AM

I would like to render a part that will supply my pages with general functionality such as rendering resources @Script.Include, @Style.Include and general background widgets like Popup windows etc. that all pages and widgets can use. How would I go about including this part with all pages when my module is enabled?

May 30, 2011 at 12:05 PM

Parts are always welded onto content items. So if you have a template that you want rendered on every page, you don't want a part. Instead you can just generate a shape from an IShapeFactory which you treat as dynamic. So you call Shape.MyShapeName() and a file called MyShapeName.cshtml will be rendered. You could do this from a Filter and then add that shape into WorkContext.Layout.

May 31, 2011 at 7:35 AM

Hi randompete, can you supply or point me to an example if this please?

May 31, 2011 at 9:33 AM

See Orchard.Framework\UI\Navigation\MenuFilter.cs; that's how the default menu gets rendered.

Also in Orchard.Widgets there is a filter that actually renders all the layers / widgets and puts them in the layout.

Jun 6, 2011 at 5:20 AM

Thank you randompete, managed to get this working through a filter over the weekend and it now saves a tremendous amount of code in all the views as I am now able to render the Telerik MVC scripts and themes as part of a filter in my module. I no longer have to add onto individual views anymore. Another side benefit I only realized after the fact is that all these controls are now available on the admin side as well so I am able to use the window and grid control's there as well. Only downside is that scripts and views are rendered to all pages which can probably be managed through exlsion onthe filter but for now it works for me as all my pages use the Telerik MVC bits. I managed to also include a setting in my module where I store the active theme so that it is easy to switch. Below is what I did in the filter and the widget view for anyone who is interested:

public class LayoutFilter : FilterProvider, IResultFilter
{
	private readonly IWorkContextAccessor _workContextAccessor;
	private readonly dynamic _shapeFactory;

	public LayoutFilter(IWorkContextAccessor workContextAccessor, IShapeFactory shapeFactory)
	{
		_workContextAccessor = workContextAccessor;
		_shapeFactory = shapeFactory;
	}

	public void OnResultExecuting(ResultExecutingContext filterContext)
	{
		var workContext = _workContextAccessor.GetContext();
		// should only run on a full view rendering result
		if (filterContext.Result is ViewResult)
		{
			var viewWorkContext = _workContextAccessor.GetContext(filterContext);
			var applicationSettings = viewWorkContext.CurrentSite.As<ApplicationSettingsPart>();
			var telerikStyle = "Default";
			if (applicationSettings != null)
				telerikStyle = applicationSettings.TelerikStyle;
			dynamic widgets = _shapeFactory.Parts_TelerikWidgets().TelerikStyle(telerikStyle);
			workContext.Layout.Content.Add(widgets);
		}
	}
}


@using Telerik.Web.Mvc.UI
@using (Script.Head()){
	Style.Require("TelerikCommon");
	Style.Require(Model.TelerikStyle);
}
@(Html.Telerik().Window()
	.Name("PopupWindow")
	.Title("PopUp")
	.Content("<iframe id='puwIFrame' frameborder='0' src='/Loading' style='border: 0; width: 98%; height: 97%;' title='Notes' scrolling='no'>This page requires frames in order to show content</iframe>")
	.Modal(true)
	.Draggable(true)
	.Visible(false)
)
@using (Script.Foot()) {
	Script.Require("jQuery");
	Script.Require("jQueryCascadeExt");
	Script.Require("jQueryTemplating");
	@(Html.Telerik().ScriptRegistrar().DefaultGroup(group => group.DefaultPath("~/Modules/Orchard.Phambili/Scripts")).jQuery(false))
}
Jun 6, 2011 at 10:54 AM

Filters are pretty powerful :)

Regarding it rendering to every single page, I'm wondering if it's possible to hijack the Layers rules engine in some generic way to control application of filters? Could be an interesting module...

Developer
Jun 6, 2011 at 1:45 PM

@Pete: I guess hijacking Layers rule engine won't be necessary. Orchard has scipting engine built-in - Widgets module is just making use of it. The idea of filter layering in the same way the widgets are is awesome! It wouldn't introduce a big performance impact though, as the script output can be cached.

Sep 18, 2011 at 4:52 PM
Edited Sep 18, 2011 at 4:53 PM

Garpo

where did you add the telerik reference for the part.cshtml?

i always get an CS0246: The type or namespace name 'Telerik' could not be found (are you missing a using directive or an assembly reference?)

Source Error:

Line 1:  @using Telerik.Web.Mvc.UI
Line 2:  @using (Script.Head()){
Line 3:      Style.Require("TelerikCommon");

 

if i add it via filter

Sep 18, 2011 at 5:11 PM
Edited Sep 18, 2011 at 5:12 PM

okay got it, it need to be added to orchard.Web

 

i tried to get rid of any references "outside the custom module"