Dec28Written by:Will
12/28/2008

A really great trend that is moving through many modules out there is the use of templates. One of these modules is the DNN core Survey module.
Module Templates
When a module developer incorporates the use of templates in their module, that opens up a door to give the power to redesign and skin the module that was never before possible. A designer could do many things, such as:
- Rewriting the HTML
- Incorporating skin class names
- Adding or removing module content
- Rearranginng the placement of module content
- And more that I haven't even thought of yet...
I think this is one of the best features that any module has come up with to this date. However, there is one really big flaw in module templates. This flaw is the lack of standardization support in the DotNetNuke core. What does that mean? It mean that right now, everyone is doing this their own way. It also means that skinners have no way to include module templates into their skin packages. I think these features are probably on the way though. (I hope.)
Let's see an example...
Survey Module Template
The DNN Core Survey Module is one of the module incorporating the template feature. By default, the first view of the survey module shows the question, and a list of possible answers.

Once the visitor chooses an option, they are shown the results of the survey module up to that point (unless the results view is turned off in the settings).

Notice that in the survey results, one of the peices of information is the total number of votes that were used to calculate the percentage. For many websites and use cases, this is not a big deal. However, there are many cases where one might not want the visitor to see this information. For example, a less-trafficked website owner may not want to know the number of visitors that voted. The template feature facilitates this need.
You can get to the module template in the module settings.

The default HTML markup for the template is as follows:
<table border="0" cellpadding="2" cellspacing="0" summary="Survey Results">
<tr>
<td valign="top" class="YourCompanyNameSurveyResults">
[SURVEY_OPTION_NAME] ([SURVEY_OPTION_VOTES])
</td>
<td align="left" valign="top" class="Normal" nowrap="nowrap">
<img src="[SURVEY_OPTION_IMAGEPATH]/red.gif" width="[SURVEY_OPTION_GRAPH_WIDTH]"
border="0" height="15" alt="" /> [SURVEY_OPTION_PERCENTAGE]%
</td>
</tr>
</table>
A small change in the code would remove the number of votes per option. Notice that the SURVEY_OPTION_VOTES token is missing.
<table border="0" cellpadding="2" cellspacing="0" summary="Survey Results">
<tr>
<td valign="top" class="YourCompanyNameSurveyResults">
[SURVEY_OPTION_NAME]
</td>
<td align="left" valign="top" class="Normal" nowrap="nowrap">
<img src="[SURVEY_OPTION_IMAGEPATH]/red.gif" width="[SURVEY_OPTION_GRAPH_WIDTH]"
border="0" height="15" alt="" /> [SURVEY_OPTION_PERCENTAGE]%
</td>
</tr>
</table>
Now, when the page loads, the number of votes is no longer visible.

I hope that this demo let you realize the beginnings of the true power that comes from template-enabled modules. I encourage you to play with the templates for the modules that have them available to you.
Technorati Tags: DNN, DotNetNuke , DNN Blog , How To , Tips , 4.09.01 , Blog Module , Survey Module
Copyright ©2008 Will Strohl
13 comment(s) so far...
I wouldn't call Survey a best practice example for templating, since it uses a poor approach of multiple replaces (one per token) which will lead into bad performance, if you want to support a larger number of tokens. DNN core already has the basis for a powerful token engine included, it is called TokenReplace, and Announcements module demonstrates, how this can be incorporated easily - supporting all system tokens as well. I created a modified version of Text/HTML with templates, I might submit to codeplex for studies and there will be other modules to follow.
By Sebastian Leupold on
12/30/2008 |
I am going to have to blog about the internal token replace engine within DNN. But what I have in mind for module developers really should be an extension of the Token Replace engine to support true "templates" for data driven modules such as The Survey, Text/HTML, and Announcements modules.
I will take a closer look at the announcements module. I already use its template engine too, as shown on the ODUG website:
http://Orlando.DotNetNukeUG.net/WhatsNew.aspx
I always love your feedback, Sebastian! Thanks for stopping by.
By Will on
12/30/2008 |
Thanks for writing this article Will and thanks mentioning the Announcements module Sebastian. I've used the basic template approach used in the Survey module, but haven't tackled the use of the core TokenReplace engine yet. If only I could go without sleep for a few months :).
By Don Worthley on
12/30/2008 |
It is my pleasure. I plan on writing more. I have a long list of topics to take care of. I too am looking forward to planning sleep... :)
By Will on
12/30/2008 |
Will,
Good article, however, I have to disagree about the "major benefits" of using the core TokenReplace engine. I have found that I get much better performance with the way that I do token replacements. Including faster execution, and less memory footprint based on profiling that I have done with both methods.
By Mitchel Sellers on
12/31/2008 |
Thanks, Mitchel!
From an overall perspective of what I have seen throughout the DNN core, I must agree on the performance comment. I continually see very little effort put forth in writing optimized code when it handles string objects. While I haven't looked at the token replacement code specifically, I have no reason to believe that it will be any better.
That being said, in an effort to provide solutions rather than just problems, I have in the past provided refactored code in Gemini that just focused on optimizing the string handling. No logic was changed in ANY way - just the methods that were used to handle the string objects. My contributions were never used. :( Such experiences really discourage me from trying again.
By Will on
12/31/2008 |
Token Replace was written with performance in mind. It was a complete rewrite in 4.6, and we adressed some more issues over the time. It is a powerfull tool when used wisely.
The memory foot print depends on the used base class - if you don't need all the system properties, it is better to inherit from Base(Custom)TokenReplace instead of TokenReplace. And sometimes a simple String.Replace or Regex.Replace is the best.
By Stefan Cullmann on
12/31/2008 |
Thanks for your input, Stefan. Very sound advice.
By Will on
12/31/2008 |
Token Replace was written with performance in mind. It was a complete rewrite in 4.6, and we adressed some more issues over the time. It is a powerfull tool when used wisely.
The memory foot print depends on the used base class - if you don't need all the system properties, it is better to inherit from Base(Custom)TokenReplace instead of TokenReplace. And sometimes a simple String.Replace or Regex.Replace is the best.
By Stefan Cullmann on
12/31/2008 |
I know, there is still a lack of documentation on TokenReplace - but what are the main advantages: - access to default object properties (dateTime:now, user, module, tab, portal, host) if needed - Stefan already pointed out, that this can be circumvented - security concerns - there are multiple access security levels, specifically for user objects to prevent exposure of e.g. profile properties without grant or passwords - formatting: you may use format strings, dates, numbers and percentages, including localized formats and a substitution for empty values Of course, this adds a small overhead, but IMHO before you start to re-implement a single of these features in your module, using a core service is a muh better strategy.
By Sebastian Leupold on
1/3/2009 |
Great points, Sebastian! I think what we really need to do is perhaps have someone with time optimize the token replace functionality (if needed), and submit it to Gemini. This way, we get the best of both worlds.
By Will on
1/3/2009 |
Hi, help me please I have a problem in the creat module . the error is : Error :msg is currently unavailable DotNetNuke.Services.Exceptions.ModuleLoadException:External Component has thrown an exception .
By m.d on
2/21/2010 |
@m.d That question has no easy answer. There are numerous issues that may come into play in trying to determine the source of that error. I would suggest trying to get help through the DNN Forums.
By Will on
2/21/2010 |