Learn More





DNN Community Blog

The Community Blog is a personal opinion of community members and by no means the official standpoint of DNN Corp or DNN Platform. This is a place to express personal thoughts about DNNPlatform, the community and its ecosystem. Do you have useful information that you would like to share with the DNN Community in a featured article or blog? If so, please contact .

The use of the Community Blog is covered by our Community Blog Guidelines - please read before commenting or posting.

DotNetNuke Tips and Tricks #13: Re-using Content with jQuery

Over the past 6 years I have watched as DotNetNuke matured into a well-rounded platform that is capable of meeting the needs of a wide variety of individuals and organizations.  One of the keys to the platform’s success is that it continues to leverage technology to make it easy to build sites the way you want. 

A user recently asked me how they could re-use the content from one page on another page in their site.  A couple of years ago I would have suggested that they make a “copy” of the module using the built-in capabilities.  This works well when you are trying to duplicate the entire content of the module, however, there are times when you just want a portion of the content.  In the past the answer would have been to split up the content on the original page – which might require changing your skin and may not be possible when using 3rd party modules.

The optimal solution would not require me to make any changes to the original page, but would instead allow me just to grab specific content and display it on a new page.  Thanks goodness we added jQuery support in 4.9 and 5.0.  This problem is really easy to solve with some simple html and a jQuery one-liner.

For a simple scenario, lets assume I want to copy the quicklinks from default template on my site’s homepage (I’m using the standard DotNetNuke install so you can follow along).  The quicklinks are a subset of the content from an HTML module on the home page.

Add a test page to your site so that we can see how this works.  The test page should come pre-installed with an HTML module.  If your copy does not, go ahead and add one now… don’t worry, I’ll wait for you to finish.

Now we edit the content in our HTML module and place a simple div in our content.

<div id="placeholderId" >This content will be replaced.</div>

I use a simple trick that Kevin Schreiner showed me a couple years ago to inject a script into my page without worrying about the HTML module stripping it out.  Open the module settings and expand the “Advanced Settings” node to display the module Header and Footer items.  We’ll place our JavaScript into the Header which is not altered when it is injected into the page.

The following JavaScript will run after the page has finished loading.

<script type="text/javascript">
        .load("http://localhost/dnn511pe/Default.aspx #QuickLinks");

The $("#placeholderId") line gets a reference to the element we defined in our HTML.  The .load method, makes an AJAX call to retrieve the home page, and then finds the content that matches the #QuickLinks selector.

All of this works really well, but this is DotNetNuke and we can make this much easier.  So lets create a simple module that handles all this drudgery for us.  I’m going to call this module ContentGrabber.

The ContentGrabber module has a simple view page that will inject our placeholder and JavaScript.  We also add a settings page because it wouldn’t be very interesting if we could only grab the quicklinks from the home page.

My view page has very little markup.  One change I did make to our original script and HTML was to add a few code expressions to allow us to specify different pages and jQuery selectors.  We also made sure to generate a unique content ID so that we could add multiple modules to the same page.

<%@ Control language="vb" 
    AutoEventWireup="false" Explicit="True" %>

<% If Not String.IsNullOrEmpty(PageURL) Then%>

<script type="text/javascript">
    jQuery(function($) {
        $("#contentGrabber_<%=moduleid %>")
            .load("<%=PageURL %> <%=Query %>");

<% End If%>

<div id="contentGrabber_<%=moduleid %>">
    Update the module settings to replace this content.

Now the only thing left to do is add some code to the code-behind to retrieve the PageURL and Query values from our module settings.  Notice that there are really only two lines of actual code, beyond the boilerplate namespace, class and property declarations.

Imports System

Namespace DotNetNuke.Modules.ContentGrabber

    Partial Class ViewContent
        Inherits Entities.Modules.PortalModuleBase

        Public ReadOnly Property PageURL() As String
                Return CType(Me.Settings(GRABBER_URL), String)
            End Get
        End Property

        Public ReadOnly Property Query() As String
                Return CType(Me.Settings(GRABBER_QUERY), String)
            End Get
        End Property

    End Class

End Namespace

So now that our view page is complete, lets create a page to handle editing our settings. 

<%@ Control language="vb" 
    Explicit="True" %>
<%@ Register TagPrefix="dnn" 
    Src="~/controls/LabelControl.ascx" %>

<table width="550" cellspacing="0" cellpadding="4" border="0" width=100%&gt;
        <td class="SubHead" width="150" valign="top">
            <dnn:label id="plPage" controlname="txtPage" runat="server" />
            <asp:TextBox ID="txtPage" runat="server" Width="300"></asp:TextBox>
    <tr id="rowWorkflow" runat="server">
        <td class="SubHead" width="150" valign="top">
            <dnn:label id="plQuery" controlname="txtQuery" runat="server" />
            <asp:TextBox ID="txtQuery" runat="server" Width="300"></asp:TextBox>

There is not much interesting going on here.  Yes, yes.  I know.  I used a table.  It’s ok.  The W3C hasn’t completely deprecated that tag yet.  If you would prefer to be semantically correct then feel free to use divs and CSS.  We’ll wait the extra 10 minutes for you to catch up.


OK.  Hopefully I didn’t lose any readers over that whole table thing.  Let’s move on the code-behind.

Imports System
Imports System.Web.UI

Namespace DotNetNuke.Modules.ContentGrabber

    Partial Class Settings
        Inherits DotNetNuke.Entities.Modules.ModuleSettingsBase

        Public Overrides Sub LoadSettings()
                If Not Page.IsPostBack Then
                    txtPage.Text = CType(ModuleSettings(GRABBER_URL), String)
                    txtQuery.Text = CType(ModuleSettings(GRABBER_QUERY), String)
                End If
            Catch exc As Exception    'Module failed to load
                ProcessModuleLoadException(Me, exc)
            End Try
        End Sub

        Public Overrides Sub UpdateSettings()

                ' update modulesettings
                Dim objModules As New DotNetNuke.Entities.Modules.ModuleController
                objModules.UpdateModuleSetting(ModuleId, GRABBER_URL, txtPage.Text)
                objModules.UpdateModuleSetting(ModuleId, GRABBER_QUERY, txtQuery.Text)

            Catch exc As Exception    'Module failed to load
                ProcessModuleLoadException(Me, exc)
            End Try
        End Sub

    End Class

End Namespace

This code was a little more involved, but still pretty simple.  I’ll leave it up to the user to create the associated resource file for our labels.  At this point we have a fully working module that packages up our original script in a nice little module with settings to handle the customizable behavior.  As you can see in the image below, both approaches provide the same results.


I have left a few exercises for the reader.

  1. Substitute the URL control for the URL setting.
  2. Add an AJAX waiting image while loading the HTML.
  3. Allow the user visually select the page element(s) they want to copy.

Download the working module from CodePlex.

Technorati Tags: , ,


Comment Form

Only registered users may post comments.


2sic Daniel Mettler (124)
Aderson Oliveira (15)
Alec Whittington (11)
Alex Shirley (10)
Andrew Nurse (30)
Anthony Glenwright (5)
Antonio Chagoury (28)
Ash Prasad (21)
Ben Schmidt (1)
Benjamin Hermann (25)
Benoit Sarton (9)
Beth Firebaugh (12)
Bill Walker (36)
Bob Kruger (5)
Brian Dukes (2)
Brice Snow (1)
Bruce Chapman (20)
Bryan Andrews (1)
cathal connolly (55)
Charles Nurse (163)
Chris Hammond (203)
Chris Paterra (55)
Clinton Patterson (28)
Cuong Dang (21)
Daniel Bartholomew (2)
Dave Buckner (2)
David Poindexter (3)
David Rodriguez (2)
Doug Howell (11)
Erik van Ballegoij (30)
Ernst Peter Tamminga (74)
Geoff Barlow (6)
Gifford Watkins (3)
Gilles Le Pigocher (3)
Ian Robinson (7)
Israel Martinez (17)
Jan Blomquist (2)
Jan Jonas (3)
Jaspreet Bhatia (1)
Jenni Merrifield (6)
Joe Brinkman (269)
John Mitchell (1)
Jon Henning (14)
Jonathan Sheely (4)
Jordan Coopersmith (1)
Joseph Craig (2)
Kan Ma (1)
Keivan Beigi (3)
Ken Grierson (10)
Kevin Schreiner (6)
Leigh Pointer (31)
Lorraine Young (60)
Malik Khan (1)
Matthias Schlomann (15)
Mauricio Márquez (5)
Michael Doxsey (7)
Michael Tobisch (3)
Michael Washington (202)
Mike Horton (19)
Mitchel Sellers (28)
Nathan Rover (3)
Navin V Nagiah (14)
Néstor Sánchez (31)
Nik Kalyani (14)
Peter Donker (52)
Philip Beadle (135)
Philipp Becker (4)
Richard Dumas (22)
Robert J Collins (5)
Roger Selwyn (8)
Ruben Lopez (1)
Ryan Martinez (1)
Salar Golestanian (4)
Sanjay Mehrotra (9)
Scott McCulloch (1)
Scott S (11)
Scott Wilkinson (3)
Scott Willhite (97)
Sebastian Leupold (80)
Shaun Walker (237)
Shawn Mehaffie (17)
Stefan Cullmann (12)
Stefan Kamphuis (12)
Steve Fabian (31)
Timo Breumelhof (24)
Tony Henrich (3)
Torsten Weggen (2)
Vicenç Masanas (27)
Vincent Nguyen (3)
Vitaly Kozadayev (6)
Will Morgenweck (37)
Will Strohl (163)
William Severance (5)
Try Evoq
For Free
Start Free Trial
a Demo
See Evoq Live
Need More Information?