Products

Solutions

Resources

Partners

Community

About

New Community Website

Ordinarily, you'd be at the right spot, but we've recently launched a brand new community website... For the community, by the community.

Yay... Take Me to the Community!

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.


Giving Our Module a Setting

We have indeed come a long way, but there is one last feature that we have not yet covered and that is giving our module a setting. What if we don’t want to show completed tasks? There is currently no way to limit whether or not the module shows complete or incomplete tasks or both. It’s currently just showing both by default. The setting that we are fixing to add will provide the flexibility to set the module to only show incomplete tasks or to show both incomplete and complete tasks.

The ModuleSettings Table
Before we start getting into the code too deep we should talk about the ModuleSettings table. Module settings are stored in what’s referred to as a “hash” table. This represents that the table holds key/value pairs and the settings for our module(s) will be stored here. In order to see where the ModuleSettings table resides open SQL Server and expand the Tables node and find the ModuleSettings table. If you right click and “Select Top 1000 Rows” you will be able to see your site’s current module settings.

Module Settings Table

Sidenote: There is also a TabModuleSettings table where settings can be stored as well. Though, TabModuleSettings are typically used when a module is shared across multiple pages, but yet there is a need to have unique settings for each location (page) on which the module is shared. We will not cover storing TabModuleSettings in this tutorial series.

Update the Settings.ascx File
Now that we know where the module settings will reside we need to discuss how we go about handling this show/don’t-show completed items functionality. Let’s first start by opening up a file that we haven’t opened much in this series… the Settings.ascx file. If you recall the Settings.ascx file is the file that shows up in the 4th tab in the module settings pop-up window.

Module Settings Tab

Currently our settings control is blank and we want to add in a simple checkbox that is going to allow site Admins to update the setting of showing completed items or not. So open up the Settings.ascx file and paste in the following code.

Show completed tasks
<asp:DropDownList ID="ShowCompletedTasksSelector" runat="server">
    <asp:ListItem Value="True">Yes</asp:ListItem>
    <asp:ListItem Value="False">No</asp:ListItem>
</asp:DropDownList>

Looking at this code we can see that this is a simple ASP.NET DropDownList control. Inside the drop-down list we offer to list items, one to say “Yes” we want to show completed tasks and one to say “No” we don’t want to show completed tasks. You may also wonder where the “Save” or “Update” button is. If you are wondering that, you are not crazy! If you notice in the module settings pop-up window there is already an “Update” button present. Because this button is already there, we don’t need to include an update button in our settings control.

Module Settings Update Button

Update the Settings.ascx.cs File
With a dropdown list ready for selections we now need to move to the code behind file for the settings control. Open the Settings.ascx.cs file. When you open the file you can see where the module development template has already provided some stubbed out code for us. Scroll down to where you see the “Public partial class Settings: MyFirstModuleSettingsBase” and replace from that line all the way to the bottom with this code:

    public partial class Settings : MyFirstModuleModuleSettingsBase
    {
        #region Base Method Implementations
        /// -----------------------------------------------------------------------------
        /// <summary>
        /// LoadSettings loads the settings from the Database and displays them
        /// </summary>
        /// -----------------------------------------------------------------------------
        public override void LoadSettings()
        {
            try
            {
                if (Page.IsPostBack == false)
                {
                    //Check for existing settings and use those on this page
                    /* uncomment to load saved settings in the text boxes*/
                    if (Settings.Contains("ShowCompletedTasks"))
                    {
                        ShowCompletedTasksSelector.SelectedValue = Settings["ShowCompletedTasks"].ToString();
                   }
                }
            }
            catch (Exception exc) //Module failed to load
            {
                Exceptions.ProcessModuleLoadException(this, exc);
            }
        }
        /// -----------------------------------------------------------------------------
        /// <summary>
        /// UpdateSettings saves the modified settings to the Database
        /// </summary>
        /// -----------------------------------------------------------------------------
        public override void UpdateSettings()
        {
            try
            {
                var modules = new ModuleController();
                modules.UpdateModuleSetting(ModuleId, "ShowCompletedTasks", ShowCompletedTasksSelector.SelectedValue);
}
            catch (Exception exc)
            {
                Exceptions.ProcessModuleLoadException(this, exc);
            }
        }
        #endregion

    }

LoadSettings
The LoadSettings function gets called whenever we access the module settings. The function populates the settings with the appropriate data. Looking at the code for the “LoadSettings” function we can see the “try/catch” block and in the try section we are checking to see if the page is a postback. If it’s not a post-back then we run a check to see if there is a setting that contains the string “ShowCompletedTasks” in the database. If there is a setting containing that string then we set the ShowCompletedTasks selector’s selected value to the value of the setting. Then, as you imagine, in the catch block we log any exceptions.

UpdateSettings
The UpdateSettings function gets called anytime we update the settings of our module. Looking at the code for the “UpdateSettings” function in the try block we create a new ModuleController. From that new controller we call the “UpdateModuleSettings” function and pass in the ModuleId, the string for the setting name, and the value to be stored with that setting. Then again we log any exceptions in the catch block.

Confirm Settings Are Saving
Now that we’ve added the code for updating our settings we should check to confirm that settings are actually being updated in the database. Rebuild your module solution and access your module’s settings. Update your setting saving either “Yes” or “No” (it doesn’t matter which one at this point) and click “Update”.

Open up SQL Server and expand your database’s tables node. Find the ModuleSettings table and then right click on it and “Select Top 1000 Rows”. Then scroll down to the bottom of the table and see if you have a new setting there called “ShowCompletedTasks”. It should look something like this:

Settings in Database

Now with our module settings correctly saving in the database we are ready to move forward.

Update the View.ascx.cs
If you think about it we’re only storing settings whenever the settings control’s “Update” button gets clicked. So technically there are no settings for our module until an Admin goes in and updates the module.  We want our module to default to showing all tasks so we’re going to update our View.ascx.cs file so that whenever the module is initially loaded we check to see if a setting for “ShowCompletedTasks” exists and if it doesn’t then we’re going to update it.

Open up the View.ascx.cs file and add in the following code to the try block of the “Page_Load” function:

  if (!Settings.Contains("ShowCompletedTasks"))
                {
                    var module = new ModuleController();
                    module.UpdateModuleSetting(ModuleId, "ShowCompletedTasks", "True");

                }

Again this code simply looks at the module settings to check if the setting already exists and if it doesn’t then updates the settings making the “ShowCompletedTasks” setting to be true.

Add the GetIncompleteTasks Stored Procedure
Now that we have our settings properly storing we need to think about our next steps. Think about it for a second… if someone chooses to not show completed tasks then we need to only show tasks that are incomplete. We could definitely loop through with jQuery and hide the DIVs that are marked as incomplete, but if we had a really long list of tasks that may not be the best route. What we need to do is to create a new stored procedure to return only the tasks that are not yet complete. Then we’ll just read the setting and call the appropriate stored procedure based on what the setting indicates.

You should feel comfortable with creating a stored procedure at this point. Open up SQL Server and create a new stored procedure with the following script:

Create Procedure CBP_GetIncompleteTasks
     @ModuleId int
AS
SELECT TaskId,
        TaskName,
    TaskDescription,
    isComplete,
    UserId,
    ModuleId
FROM CBP_Tasks
WHERE ModuleId = @ModuleId AND isComplete = 0

GO

Notice we simply pass in the module ID again so we can scope at the module level and then we’re selecting task data where the ModuleId in the table equals the module id passed in as the parameter AND where the isComplete field equals 0 or in other words… false. This stored procedure will return only the incomplete tasks. Execute the stored procedure to test that it works and be sure to pass in the appropriate ModuleId.

Update SQLDataProvider File
Yep, you guessed it… we now need to update our SQLDataProvider files with the appropriate code for this new stored procedure. Update your SQLDataProvider files with the following.

IF EXISTS (select * FROM dbo.sysobjects WHERE id = object_id(N'{databaseOwner}[{objectQualifier}CBP_GetIncompleteTasks]') and OBJECTPROPERTY(id, N'IsProcedure') = 1)
    DROP PROCEDURE {databaseOwner}{objectQualifier}CBP_GetIncompleteTasks
GO
Create Procedure {databaseOwner}{objectQualifier}CBP_GetIncompleteTasks
    @ModuleId int
AS
SELECT TaskId,
        TaskName,
    TaskDescription,
    isComplete,
    UserId,
    ModuleId
FROM {databaseOwner}[{objectQualifier}CBP_Tasks]
WHERE ModuleId = @ModuleId AND isComplete = 0
GO
And the UninstallSqlDataProvider file with:
IF EXISTS (select * FROM dbo.sysobjects WHERE id = object_id(N'{databaseOwner}[{objectQualifier}CBP_GetIncompleteTasks]') and OBJECTPROPERTY(id, N'IsProcedure') = 1)


Update the Uninstall SQLDataProvider File
Update the uninstall SQLDataProvider file with the following:

IF EXISTS (select * FROM dbo.sysobjects WHERE id = object_id(N'{databaseOwner}[{objectQualifier}CBP_GetIncompleteTasks]') and OBJECTPROPERTY(id, N'IsProcedure') = 1)
DROP PROCEDURE {databaseOwner}{objectQualifier}CBP_GetIncompleteTasks

Update the TaskController.cs File
With our stored procedures in place we are ready to update our TaskController.cs file to make use of the stored procedure that we just created. This controller will be similar to the GetTasks controller in syntax. Open the TaskController.cs file and paste in the following code:

public IList<Task> GetIncompleteTasks(int ModuleId)
        {
            return CBO.FillCollection<Task>(DataProvider.Instance().ExecuteReader("CBP_GetIncompleteTasks", ModuleId));

         }

In this code we create an IList of Task objects called “GetIncompleteTasks” passing in the module Id and we call the ExecuteReader method and pass in the string name of the stored procedure that we just created. In this case it is the CBP_GetIncompleteTasks stored procedure which also expects the module Id as a parameter.

Update the WebServices.cs File
Following suite we will now create a new web service. Can you guess how to do all this already? Open your WebServices.cs file and include the following code:

     [AllowAnonymous]
     [HttpGet]
      public HttpResponseMessage GetIncompleteTasks(int moduleId)
        {
            try
            {
                var tasks = new TaskController().GetIncompleteTasks(moduleId).ToJson();
                return Request.CreateResponse(HttpStatusCode.OK, tasks);
            }
            catch (Exception exc)
            {
                return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, exc);
            }

        }

Here again in the try block we create a new web service route that instantiates a new TaskController and this time calls the GetIncompleteTasks method passing in the ModuleID. Then we return the incomplete tasks JSON object on the response.

You should be able to test out the web service to see if it works now by accessing the appropriate URL for your service route. For me that URL is:

http://moddev2.loc/DesktopModules/MyFirstModule/API/ModuleTask/GetIncompleteTasks?moduleId=416

Get Incomplete Tasks Web Service JSON Object

Upon accessing your web service you should see a JSON object there awaiting you. If so, then congrats… we are ready to move forward!

Update the View.ascx File
Now for the last and critical step here. We have done all the necessary work to incorporate a setting into our module, but yet we need to read from this setting and access a particular web service route based on the setting.

Open the View.ascx file and in the JavaScript code block we need to update the top portion. We’re going to create a new variable and update the loadTasks() function with the following:

<script type="text/javascript">
    var ShowCompletedTasks = '<%= Settings["ShowCompletedTasks"].ToString() %>';
   
function loadTasks() {     
        if (ShowCompletedTasks == "True") {
            GetTasksVariableURL = "/DesktopModules/MyFirstModule/API/ModuleTask/GetTasks?moduleId=" + moduleId;   
        }
        else {
            GetTasksVariableURL = "/DesktopModules/MyFirstModule/API/ModuleTask/GetIncompleteTasks?moduleId=" + moduleId;
        }
        $.getJSON(

        GetTasksVariableURL,

Notice the variable “ShowCompletedTasks”. We are here again setting a JavaScript variable equal to a server side value. The <% = signs give it away. From the server we are getting the “ShowCompletedTasks” setting and converting it to a string. The ShowCompletedTasks variable will be a string of either “True” or “False”.

Just after we get the variable we run an “If” statement and if the ShowCompletedTasks setting is true then we simply access the GetTasks web service and if it’s false then we access the GetIncompleteTasks web service.

Also notice that I abstracted the URL of our jQuery “GetJSON” function to be a variable so that we can dynamically replace it. Check out the last few lines of code in this snippet where the $.getJSON(… now has the “GetTasksVariableURL” there. So we update the GetTasksVariableURL in the if statement and then pass that varying URL into the $.getJSON jQuery method and that’s all we need to do!

Now time to test it out. Go into your module settings and update the setting to being either “Yes” or “No” and see if your task list updates accordingly.

The video below walks through the concepts covered in this blog entry

Summary
In this entry we walked through the process for creating a setting and now have our module successfully responding to our setting. Congrats if you’ve made it this far! We are getting to the short rows indeed. Now with our module functioning correctly we are ready to illustrate, in the next blog entry, just why we’ve been updating these SQLDataProvider files throughout this entire series.

Go to the Next Blog Entry: Installing Our Module in Another DNN Instance

Comments

James Brown
Link to the series introduction
http://www.dnnsoftware.com/community-blog/cid/155064/module-development-for-non-developers-skinners-dnn-beginners--blog-series-intro

Link to the previous Blog Entry:http://www.dnnsoftware.com/community-blog/cid/155090/deleting-tasks
James Brown Monday, June 15, 2015 11:48 AM (link)

Comment Form

Only registered users may post comments.

NewsArchives


Aderson Oliveira (22)
Alec Whittington (11)
Alessandra Daniels (3)
Alex Shirley (10)
Andrew Hoefling (3)
Andrew Nurse (30)
Andy Tryba (1)
Anthony Glenwright (5)
Antonio Chagoury (28)
Ash Prasad (37)
Ben Schmidt (1)
Benjamin Hermann (25)
Benoit Sarton (9)
Beth Firebaugh (12)
Bill Walker (36)
Bob Kruger (5)
Bogdan Litescu (1)
Brian Dukes (2)
Brice Snow (1)
Bruce Chapman (20)
Bryan Andrews (1)
cathal connolly (55)
Charles Nurse (163)
Chris Hammond (213)
Chris Paterra (55)
Clint Patterson (108)
Cuong Dang (21)
Daniel Bartholomew (2)
Daniel Mettler (181)
Daniel Valadas (48)
Dave Buckner (2)
David Poindexter (12)
David Rodriguez (3)
Dennis Shiao (1)
Doug Howell (11)
Erik van Ballegoij (30)
Ernst Peter Tamminga (80)
Francisco Perez Andres (17)
Geoff Barlow (12)
George Alatrash (12)
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 (274)
John Mitchell (1)
Jon Henning (14)
Jonathan Sheely (4)
Jordan Coopersmith (1)
Joseph Craig (2)
Kan Ma (1)
Keivan Beigi (3)
Kelly Ford (4)
Ken Grierson (10)
Kevin Schreiner (6)
Leigh Pointer (31)
Lorraine Young (60)
Malik Khan (1)
Matt Rutledge (2)
Matthias Schlomann (16)
Mauricio Márquez (5)
Michael Doxsey (7)
Michael Tobisch (3)
Michael Washington (202)
Miguel Gatmaytan (3)
Mike Horton (19)
Mitchel Sellers (40)
Nathan Rover (3)
Navin V Nagiah (14)
Néstor Sánchez (31)
Nik Kalyani (14)
Oliver Hine (1)
Patricio F. Salinas (1)
Patrick Ryan (1)
Peter Donker (54)
Philip Beadle (135)
Philipp Becker (4)
Richard Dumas (22)
Robert J Collins (5)
Roger Selwyn (8)
Ruben Lopez (1)
Ryan Martinez (1)
Sacha Trauwaen (1)
Salar Golestanian (4)
Sanjay Mehrotra (9)
Scott McCulloch (1)
Scott Schlesier (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)
Steven Fisher (1)
Tony Henrich (3)
Torsten Weggen (3)
Tycho de Waard (4)
Vicenç Masanas (27)
Vincent Nguyen (3)
Vitaly Kozadayev (6)
Will Morgenweck (40)
Will Strohl (180)
William Severance (5)
What is Liquid Content?
Find Out
What is Liquid Content?
Find Out
What is Liquid Content?
Find Out