Happy New Year blogosphere and welcome to post ‘numero uno’ for 2011 from BondiGeek.

I have the good fortune of being down in Cape Town, South Africa for the first couple of weeks of 2011 so if you see a gratuitous lion, giraffe or elephant photo slip in to one of my posts do not be alarmed Smile

So todays post is all about jQuery Templates and specifically the use of the {{if}} and {{else}} Template Tags.

You can find the API for jQuery Templates over here if you would like to learn more about this rather lovely technique for performing client side binding of data.

Now jQuery Templates are more about presentation but a few tags have been supplied for looping and conditional logic (see also {{each}}) and I finally used these yesterday to clean up some javascript code I had with embedded mark-up which is messy at the best of times with all those pesky ‘,” and +’s.

I just finished, from the development side, a piece of work that is going to be used for an Optus/Samsung Australian Open Tennis Promotion. Go the Samsung Galaxy TAB! Must lay my hands on one of these babies and compare to my iPad. I do like the size of the Galaxy TAB and the weight as I am convinced after 8 months of use of the iPad I am doing some serious RSI damage to my hand and forearm due to the weight of that sucker.

But I digress. On to the code stuff.

The screenshot below shows the mark-up that I was required to render, which is basically a table with a column for Action buttons. However, depending on the Status of each row the buttons to be rendered vary. Not mind blowing stuff here folks but a Presentational and Functional problem that jQuery Templates are well suited to.

Samsung/Optus Australian Open Promotion

Initially I had used just JavaScript to solve the problem but to be honest I was never happy with the amount of string concatenation going on and all that embedded mark-up in my JavaScript. Messy, messy, messy.

var rows = ""; for (var i = 0; i <= results.length - 1; i++) { var className = "odd-row"; if (i % 2 0) { className = "even-row"; } rows += "" rows += ""; rows += "" + results[i]["RegistrantId"] + ""; rows += "" + results[i]["FirstName"] + ""; rows += "" + results[i]["LastName"] + ""; rows += "" + results[i]["InvoiceNumber"] + ""; rows += "" + results[i]["RegistrantStatu"]["RegistrantStatusName"] + ""; rows += "" + RenderActions(results[i]) + ""; rows += "" + "" + ""; rows += "
Notes:"
} $("#results-panel table tbody").append(rows);

I don’t know about you but I hate having to maintain code like that in JavaScript.

And on top of all that we have that RenderActions method embedded in their as well which is the bit that did the job of deciding which buttons to create.

function RenderActions(registrant) { var buttons = ""; switch (registrant["RegistrantStatusId"]) { case 1: buttons = "" + ""; break; case 2: buttons = ""; break; case 3: buttons = ""; break; case 4: if (registrant["ApprovedOn"] != null) { buttons = ""; } break; } return buttons; }

So having used jQuery Templates on the past few projects on I decided it was time to grab the bull by the horns and use some of the logic Tags and solve the problem that way.

Once I had created my templates (yes I meant to say plural their and I will explain shortly) I ended up with just the following javascript:

for (var i = 0; i <= results.length - 1; i++) { if (i % 2 0) { $("#even-row-template").tmpl(results[i]).appendTo("#results-panel table tbody"); } else { $("#odd-row-template").tmpl(results[i]).appendTo("#results-panel table tbody"); } }

Now you will note that their is an Odd and an Even template listed above ($(“#even-row-template”) + $(“#odd-row-template”)) and that is why I used plural. I am pretty sure I can use the {{each}} tag so I can remove that looping logic completely by binding directly to the results variable (which is just an Array of Objects) and remove the necessity for 2 templates. However, time constraints and deadlines mean I will have to let that one brew in my mind and refine later or on the next project. Rest assured once I figure it out another blog post will be written.

And in case you are wondering what the differences in the Odd and Even templates are it is purely styling so I have the alternating row colours.

So on to the Template:

So the Template above contains both the Presentational and Conditional logic required to render each row of the table. Depending on the RegistrantStatusId the Actions column outputs different buttons or none at all. That is what all thoss {{if}} statements are for.

And if you look at the line {{if RegistrantStatusId4}} you will notice below that the use of the {{else}} tag. Since a Registrant is either Approved or Rejected we can just check the date of ApprovedOn and if it is null fall through to the {{else}}

When a Row (ie. Object) is bound to the template using the line of Javascript below the ${} template tags are used to pull out the various pieces of data required. This binding process also kicks off all that conditional logic on a per row basis.

$("#odd-row-template").tmpl(results[i]).appendTo("#results-panel table tbody");

If you are using WCF Data Services and OData, which if you are not aware of by now I am a huge fan of, you can also access data items in child entities that are related to the Object you are binding to, provided you have used the $expand query option.

The code snippet below(which is completely unrelated to the above) shows you what I mean. The first line is the url I am using for my Ajax call to the WCF Data Service and at the end of that I have added the ‘$expand=State,Product’ query option which tells it to also return the State and Product data for the Registrant from the related tables.

The rest of the script is an additional template I use for the details of a Row and is what the little down arrow on the end of each row is for. Note the binding tags ${State.StateName} and ${Product.ProductName} which tell the template to look at the State and Product items of the Registrant and get the StateName and ProductName respectively from the related tables.

var url = "/data/RegistrationService.svc/Registrants(" + registrantId + ")?$expand=State,Product";

Ok so now that we have all that out of the way, lets look at this and decide if it is a better solution.

If you look at the shear lines of code written they are not to different so this is not an exercise in saving us lines necessarily.

However, if you look at the end solution I hope you will agree that it is much cleaner. No more embedded mark-up with string concatenation which personally I loath and is what a lot of older JavaScript looks like. It’s a nightmare to debug.

The lines start to get a little blurry however when you look at the conditional logic in the Actions row. It is pretty clear to me now why they have chosen to only add a few conditional tags to the API otherwise it could start to get a little messy.

Weighing it all up though I much prefer the final solution which is cleaner and easier to maintain.

Now if only I can figure out how to apply the {{each}} tag I can get rid of that final loop once and for all and 50% of my template Smile

Happy New Year

BondiGeek