Umbraco widgets – razor way
We have been working on an interesting project lately and as usual, with every new project there is some new Umbraco implementation trick we learn. That is the power of Umbraco and what I love about it, you can do almost anything, it is the most flexible system I ever used.
In this particular case, client had couple of complex templates on the site where page consisted of several “modules”. One module was a classic rich text, other was a Javascript slider used for notifications (or testimonials, quotes, etc.), then another one with some statistics data nicely formatted, etc. Normally, this is a standard page in Umbraco but client wanted to make each of those modules optional (none, one, or many modules of each type) and they wanted to be able to sort them on the page. Lastly, they wanted this functionality on almost every page of the site!
After initial search for “widget” packages in Umbraco repository, we decided not to use any package. Here is how we implemented this:
We will create a “widgets folder” node as a child node of each page where we wanted to use this functionality. This folder is going to be a container of modules (we call them widgets). Then, macro on the page will search for this folder and if found, go one by one module and render its content on the page. Simple! If you don’t want modules on a page, just don’t create this folder. If you want to add more modules, just create them in this folder. And if you want to sort them, use Umbraco’s content sort feature to sort nodes in the folder.
Step by step
I’m assuming you already have a site with some content and templates
done.
var widgetsFolder = Model.WidgetsFolders.Where("Visible").First();
- Create “WidgetsFolder” doctype – no properties are needed, we will use this only as a container of page modules.
- Create doctypes for modules, one for each. You can start with a very simple one: “Widget_RichText” which will have only 2 properties: title (textstring) and content (RTE).
- Edit structure data of doctypes: a) Make sure Widget_RichText is allowed child of WidgetsFolder and b) WidgetsFolder is allowed child of any doctype you wish to enable modules for.
- Enter some test content. Pick a page, create subnode for it of type WidgetsFolder (I also like to sort all subnodes so this one is on the top). Now, create a subnode of this one, and choose Widget_RichText as type. Enter some test title and content too. You might want to make sure WidgetsFolder is ignored in your scripts that create page navigations. You don’t want this page in your main navigation!
We’re ready to start writing some code. - Create a razor script named “RenderWidgets” (yes, let Umbraco create a macro for you). this macro will search for WidgetsFolder under the current page and, if found, loop through each widget there and render it. This is the code with some comments:
Search for WidgetsFolder and only take first one if there is more than one:
Now we can loop through widgets in the folder. I’m considering only doctypes starting with “Widget_”. This is not necessary because structure of WidgetsFolder defined in step 3 does not allow other doctypes as children anyway. I’m using it here only as an example for implementations where widgets are not stored in WidgetsFolder but as normal child nodes of the page. However, I like to keep things neat and separate widgets from content.:
@foreach (dynamic widget in widgetsFolder.Children.Where("Visible and nodeTypeAlias.StartsWith("Widget_")")) {
string widgetType = widget.NodeTypeAlias.ToString();
switch (widgetType) {
case "Widget_RichText":
@showRichText(widget);
break;
case "Widget_Slider":
@showSlider(widget);
break;
default:
Unknown Widget!
break;
}
}
As you can see, I’m calling showRichText helper to render widget content. To keep this example short, I’ve included only 2 widget types, Widget_RichText and Widget_Slider. First helper is really simple:
@***RICHTEXT template ***@
@helpershowRichText(dynamic widget) {
@widget.title
@widget.content }
My slider widget is a bit more complex because it uses a uComponents data type Grid, with 2 columns (simple editor for content and text string for signature). All this is turned into slider using Flexslider javascript.
@*** SLIDER template ***@
@helpershowSlider (dynamic widget) {
@foreach (var item in widget.content) {
@Html.Raw(item.content.ToString())
@item.byLine
}
}
Thats’ all! isn’t it simple? Only one step left:
6. Insert RenderWidgets macro into proper page template and test!
Now, you can edit helpers in macro to fit your design. Those helpers are basically templates of widgets. You can add many more widgets like this using the same system: 1) create doctype for it, 2) allow it as child of WidgetsFolder, 3) add template (helper) to razor script… done!
Let me know if this helps with any of your implementations!
Got a project?
Let's talk.
Like what you see?
Or have a project, idea, requirement or scope.