Enhance Sitefinity widget re-usability with template selector and filtering
In the last post, we looked at creating reusable common collections of fields for Sitefinity widgets. We did this by leveraging a combination of Interfaces and MVC partials. If it wasn’t immediately clear as to why one would go to the effort of using this method to add a couple of fields to a widget, we do this to create a process that is scalable and reusable. For the singular use we showed prior, it certainly might seem like overkill for the purposes required. However, if we think ahead and consider the widgets we might have to build in the future, the widgets we don’t yet know the requirements of, the widgets we have yet to define, design and build for future projects. With this in mind, we find it much better practice to standardise our coding practices and produce elements which standardise our output. While the short-term effort might seem like more than is required for such a simple use, the long-term benefits quickly speak for themselves. We can reuse these collections more readily and more quickly once the implementation is completed once. There are further knock on benefits; we know these fields have been tested so can reuse them with confidence. We know the collections have been integrated in other widgets already so the likelihood of there being significant errors or problems in the integration is greatly diminished. We also know that the code used has been signed off, standardising and improving our overall coding practices. This greatly improves the overall stability of our code and ensures it meets our own internal standards.
So, once we have this code written, what happens? Surely there’s not one size fits all with this code? Clients have different requirements and different expectations as to how widgets function. Today, we’re going to look at using these practices to create and use the same widget in multiple ways.
To do this we will use common widget template naming convention (widgetname.template.cshtml) and some modifications to the widget controller.
Add the following template name variables to your controller:
private string templateName = "DemoWidget";
public string TemplateName
this.templateName = value;
Change the index method to use the selected template for the view rather than the default "index".
Create re-useable Template Selector
In the designer view we need a dropdown selector to choose from available templates. This will be a list of ‘.cshtml’ files that fit the pattern. Like in the previous article, we make this re-usable for any widget by creating a template selector shared partial view (_TemplateSelector.cshtml in the /MVC/Views/Shared folder in the Github).
We define a model of type String so we can specify the naming convention to match (i.e. our widget prefix).
Add the partial view to our Designer View
Rename frontend view to match naming convention and test
We rename our template from “index.cshtml” to “DemoWidget.index.cshtml”
Once you build your solution and run the site, your widget designer should now look like this with one template choice:
Using template naming convention to filter your widgets features available to content editors
Now we can get adaptive. Say for example the above widget would suit another section of the website but that there is no need for the images to be responsive. Our only requirement is that the widget supports a single image. Previously, we would have created a new widget for the single image but the more efficient method is to create a new frontend view template within this current widget. Both options are fine, but for a content editor it might be confusing, especially if there are multiple fields that aren’t used for all templates.
The solution to this is to use our template naming as a way of filtering features in the designer view.
For example, we might require the template name includes “.Responsive” in the name to show the responsive image selector otherwise we just show one.
Create two templates, one using the name to indicate it is responsive
We Create our two template variations: DemoWidget.Responsive.cshtml and DemoWidget.Single.cshtml:
With this change, in our designer view we want to only show one image selector when the single template is selected and show the two selectors when the responsive template is selected. We can use the AngularJS ‘ng-show’ Directive which allows us to evaluate an expression to decide whether to show an element or not. We create our two alternatives and apply the ng-show as follows:
We check whether the TemplateName property contains “Responsive” or not and display the appropriate designer markup.
Again, once you build and run your site and the widget designer should now look like this:
Widget Editor (Responsive):
Widget Display (Responsive):
Widget Editor (Single):
Widget Display (Single):
And that’s it! As you can see, using this practice creates a far better user experience for the site administrator. Rather than having to drop in lots of different widgets of similar types to accommodate different requirements, the site admin drops in one widget which has multiple views depending on the current requirements. This leads to less “widget clutter” (having many widgets to choose from) and makes the process simpler and more streamlined for the site admins. We’ve also optimised our code, reusing the partials required and intelligently adapting them to match our requirements.
Reusing code is the holy grail of development. The more we can write scalable and reusable code, the less problems we run into as a whole and the faster our development process and cycle becomes. Sitefinity is a highly adaptable CMS and with its regular release cycle, leverages the best aspects of what .NET has to offer. While none of these processes are particularly difficult to understand or use, documentation explaining these practices seems limited. I hope this helps you to improve your widgets and optimise them to their full potential.
If you or your company are looking for further advice or assistance in this domain, or would like to discuss your digital strategy, give us a call!