We’ve come a long way thus far and in our last blog we were able to get our Tasks table data returned as a JSON object via our web service. In this blog we’re going to return to our view control and update it so that we can get these tasks surfaced in our view control. In order to do this we’ll use jQuery, a popular JavaScript library, to help us do some dynamic manipulating of both the layout and data in our view. If you’re not familiar with jQuery I’ve provided some links at the bottom of this blog entry that will be helpful.
Sidenote: As I just mentioned we will use jQuery in this tutorial, but you could definitely use other JavaScript libraries such as Angular if you like. Just whatever floats your boat!
Updating the code in our View
Now it’s time to get into some code and get these tasks to show in our module already! One important thing to note is that DNN loads and uses jQuery by default. Thus, we don’t need to register any scripts or make calls to CDN’s because jQuery is already in the house and being used.
Open up the View.ascx file in Visual Studio and go into the “Code view”. We’ve previously coded and styled this to give us the two grey boxes in our view. The DIV on the left is for adding tasks and the DIV on the right is for listing out the tasks as we add them. Currently we’ve got some placeholder information in the Task List DIV on the right. All we have to do is to write some jQuery to get these tasks showing up.
Beneath the last closing </DIV> tag start a script block. For any of you front-end developers this will be something you’re used to, but for anyone who is new it may not be. For that reason we’re going to be as thorough as possible. To start a script block just include this code
<script type =”text/javascript”>
</script>
Now with our script block started we need to include some jQuery code to go out and fetch our JSON that is awaiting us. JQuery has a short-hand AJAX (asynchronous JavaScript and XML) method for fetching JSON and we will make use of it. You can find out more about this $.getJSON function on the jQuery page and on the w3Schools page.
Update your script block to read:
<script type="text/javascript">
$.getJSON(
"/DesktopModules/MyFirstModule/API/ModuleTask/GetTasks?moduleId=416",
function (result) {
var parsedTaskJSONObject = jQuery.parseJSON(result);
console.log(parsedTaskJSONObject);
});
</script>
Now let’s discuss this code here to gain more understanding. The first line we see is the $.getJSON and that is jQuery’s shorthand method for grabbing JSON via AJAX. On the next line you see a URL and this URL just happens to be the URL that points to our web service where our JSON object is awaiting us. After the URL we see “function(result)” and what this represents is that we are about to create a function based on the resulting data of our JSON call.
Next we create a variable, in this case named, “parsedTaskJSONObject” which is set equal to the result of our “result” object being parsed by jQuery’s parseJSON method. This variable name is probably too long for most, but I'm going to name it that just for clarity's sake. Then we instantly turn around and put in a “console.log(parsedTaskJSONObject);”. This “console.log” will log whatever we pass into it into the console, which makes it easy for us to check as to whether or not we’re really getting any data back. You may wonder where the console resides. Most browsers have F12 tools with a console in them. I’m using Google Chrome and when using Chrome just click F12 and you’ll see the toolbar pop up. Then just click on the last option which is the console. If you’ve done everything correctly then you should be seeing some objects returned there. Expand those nodes and you should see our dummy data task object information there. It should look similar to this:
If you see those objects then congrats, you’re making progress and we’re almost there. As a side note I frequently use the console.log method in order to check what’s going on within my JavaScript. If you ever wonder what is happening just console.log the information. Now that we’re cooking with gas let’s keep right on trucking.
Time to Loop Through Some Objects
We are successfully getting our data back as objects and now we need to do something with them. Update your code to read as the following and click save:
<script type="text/javascript">
$.getJSON(
"/DesktopModules/MyFirstModule/API/ModuleTask/GetTasks?moduleId=416",
function(result) {
var parsedTaskJSONObject = jQuery.parseJSON(result);
console.log(parsedTaskJSONObject);
$.each(parsedTaskJSONObject, function () {
console.log(this.isComplete + this.TaskName + this.TaskDescription);
});
});
</script>
Once you click save and reload the website look in the console and see what’s there. You should see something that looks similar to this:
The reason we see all the information for each object on a row is because we just put in a loop and logged it all. If you look back up at the code just after the console.log(parsedTaskJSONObject) you see the jQuery syntax of $.each(parsedTaskJSONObject, function(){…}. This tells our code to loop through each JSON object and execute a function on that object. In our case, at least at the moment, our function that happens on each object is to simply logging the information of each object. Pay attention to the “this” syntax. When we say “this” we are referring to “this” object … in other words… the current object that we are looping through. After the “this” we tag the isComplete, TaskName, & TaskDescription properties of our objects.
This confirms that we can successfully loop through our objects and grab each individual object. Now we need to take these objects and insert them into our TaskList on the right hand side of the screen. Next update your script to the following, save it, then reload the page:
<script type="text/javascript">
$.getJSON(
"/DesktopModules/MyFirstModule/API/ModuleTask/GetTasks?moduleId=416",
function (result) {
var parsedTaskJSONObject = jQuery.parseJSON(result);
$.each(parsedTaskJSONObject, function () {
if (this.isComplete == true) {
$('.ListItems').append(
'<div class="checkbox"><input class="cbxListIsComplete" type="checkbox" checked/></div>' +
'<div class="ListTaskName">' + this.TaskName + '</div>' +
'<div class="ListTaskDescription">' + this.TaskDescription + '</div>');
}
else {
$('.ListItems').append(
'<div class="checkbox"><input class="cbxListIsComplete" type="checkbox"/></div>' +
'<div class="ListTaskName">' + this.TaskName + '</div>' +
'<div class="ListTaskDescription">' + this.TaskDescription + '</div>');
}
});
});
</script>
Did you now get some data back in the module? If so, congrats… you’re moving right along! Let’s talk about this updated script. In this updated script we simply add in some new logic in the loop where we previously logged the items. We first run a check to see if the “isComplete” property is true for the current item we’re looping through. If it is true then we use jQuery to append some text to the “ListItems” DIV. You may wonder why we are doing it this way. Well I also am wondering why kind of… The whole reason we’re doing this is because we want the checkbox to be checked if the isComplete value is true and not checked is the value of isComplete is false. After doing some research it seems the only way we can get this to render correctly is to either include the “checked” syntax or not. There is no way to set it to true or false directly in the html that I can figure out. If you can figure a way to do this then please let us know in the comments below this blog entry.
Looking specifically at the loop we see:
$('.ListItems').append(
'<div class="checkbox"><input class="cbxListIsComplete" type="checkbox" checked/></div>' +
'<div class="ListTaskName">' + this.TaskName + '</div>' +
'<div class="ListTaskDescription">' + this.TaskDescription + '</div>');
}
and on each line we are adding in a div with the checkbox syntax either present or not and then we’re adding in the + symbols because that’s how we concatenate in JavaScript. So whenever we hit a point where we want to add in a value from our object we then use the “this.TaskName” syntax. This is how we iterate through each item and log it to the screen. Fun stuff huh?
* UPDATE
The Shaun Walker has submitted a way to fix the checkbox "checked" scenario, which is really straight forward & simple (slapping myself here for not thinking about it previously). In order to not have to repeat the DIV items simply use the below code... and thanks Shaun!:
var checked = '';
if (this.isComplete == true) {
checked = ' checked';
}
$('.ListItems').append(
'<div class="checkbox"><input class="cbxListIsComplete" type="checkbox"' + checked + '/></div>' +
'<div class="ListTaskName">' + this.TaskName + '</div>' +
'<div class="ListTaskDescription">' + this.TaskDescription + '</div>');
Did you notice that the placeholders are still there? Let’s take them out so that only the real data is showing now. To remove the placeholder data just go back up to the “ListItems” DIV and delete the 3 child DIVS and you should be good to go.
While you might think we’re through we still have one bit of business to take care of at the moment. Again we have hard coded the URL into the script. And you’re probably already saying it here before you read it, but we can’t hard code the moduleId because that value will change dynamically. So how can we account for this? It’s not too bad to pull off actually. Update your script to read as follows, click save, then reload:
<script type="text/javascript">
var moduleId = <%= ModuleId %>;
$.getJSON(
"/DesktopModules/MyFirstModule/API/ModuleTask/GetTasks?moduleId=" + moduleId,
function (result) {
var parsedTaskJSONObject = jQuery.parseJSON(result);
$.each(parsedTaskJSONObject, function () {
if (this.isComplete == true) {
$('.ListItems').append(
'<div class="checkbox"><input class="cbxListIsComplete" type="checkbox" checked/></div>' +
'<div class="ListTaskName">' + this.TaskName + '</div>' +
'<div class="ListTaskDescription">' + this.TaskDescription + '</div>');
}
else {
$('.ListItems').append(
'<div class="checkbox"><input class="cbxListIsComplete" type="checkbox"/></div>' +
'<div class="ListTaskName">' + this.TaskName + '</div>' +
'<div class="ListTaskDescription">' + this.TaskDescription + '</div>');
}
});
});
</script>
Your module still should have worked. Did you see what we did? We created a variable called “moduleID” then concatenated it to the string of the URL. We actually surfaced a server-side value and exposed it as a string and set it to a variable. When you see the “ var moduleID = <%= ModuleId %>; those percentage signs are letting us know that it’s server code. If you want to, feel free to console.log that variable to ensure it’s coming through. Once we get that variable we then update the URL that we’re referencing and concatenate the moduleId to the end of the string and that’s all it takes.
That wasn’t much code, but it did make for a long blog. Though, I wanted to elaborate on it in a step by step method in hopes of making it easier to understand because I’m more concerned with you learning than simply being able to click and refresh. Hopefully it’s helpful.
Did you just successfully get your tasks returned to the view control? If so, tweet to me and let me know!
The below video walks through the concepts covered in this blog
Summary
In this blog entry we made use of jQuery to not only fetch the JSON data that we previously created, but to also loop through our objects and update the view. We have indeed come a long way and we’re just about there. Now that we’re at a decent stopping point in the next blog I want to take a second and reflect on our journey thus far so that we can mentally tie all the strings together. Yes, it will be somewhat repetitive, but then again repetition is the mother of learning. Hope to see you there!
Helpful JQuery links:
Go to the Next Blog Entry: "Mentally Mapping the Pieces Together"