Use jQuery and ASP.NET AJAX to build a client side Repeater
AJAX, ASP.NET, JavaScript, jQuery, UI By Dave Ward. Updated April 2, 2012Note: This post is part of a long-running series of posts covering the union of jQuery and ASP.NET: jQuery for the ASP.NET Developer.
Topics in this series range all the way from using jQuery to enhance UpdatePanels to using jQuery up to completely manage rendering and interaction in the browser with ASP.NET only acting as a backend API. If the post you're viewing now is something that interests you, be sure to check out the rest of the posts in this series.
There was some interesting discussion on Matt Berseth‘s blog recently, regarding methods for building and displaying markup on the client side. Though I haven’t posted any examples here before, rendering markup on the client is a technique that I use often and recommend.
By sending only data to the client, you can profoundly reduce the size of what you send and see a substantial increase in performance. You also allow yourself the ability to easily add features like light-weight sorting and paging on the client. This can not only improve your users’ experience, but reduce server load and bandwidth requirements.
To that end, I’m going to walk you through these four steps to effectively implementing a client side Repeater, using ASP.NET AJAX and jQuery:
- Create an RSS Reader page method to return JSON data to the client.
- Call that page method with jQuery.
- Use the returned data to build a table on the client side.
- Improve upon the table creation with a templating plugin.
Creating an RSS reader page method
Because web browsers prohibit cross-domain AJAX functionality, displaying items from an external RSS feed is a good real-world example. To overcome this limitation, our first step is to write a local server side proxy to relay that feed data to the client.
A web service or page method is ideal for this task. I would typically use an ASMX web service, but let’s use a page method here. It’s useful to illustrate how nearly interchangeable the two really are.
[WebMethod] public static IEnumerable GetFeedburnerItems(int Count) { XDocument feedXML = XDocument.Load("http://feeds.encosia.com/Encosia"); var feeds = from feed in feedXML.Descendants("item") select new { Date = DateTime.Parse(feed.Element("pubDate").Value) .ToShortDateString(), Title = feed.Element("title").Value, Link = feed.Element("link").Value, Description = feed.Element("description").Value }; return feeds.Take(Count); }
This page method uses LINQ to parse a few details out of the RSS feed, create an anonymous type with that data, and then return a collection of those anonymous types. By selecting only the data we’re interested in on the server side, we can minimize the traffic between client and server.
In response to my recent deferred content loading post, several of you asked how to limit the results, so I added that this time around. The Take extension method performs this task for us.
Calling the page method with jQuery
On the client side, the first thing we need to do is initiate a request to the page method. We’ll do this with jQuery’s ajax() method:
$(document).ready(function() { $.ajax({ type: "POST", url: "Default.aspx/GetFeedburnerItems", // Pass the "Count" parameter, via JSON object. data: "{'Count':'7'}", contentType: "application/json; charset=utf-8", dataType: "json", success: function(msg) { BuildTable(msg.d); } }); });
When the page loads, this function will perform an AJAX request to our page method, requesting information on the first seven feed items. When the response arrives, a JavaScript function will be called with the response data.
If you are unfamiliar with this jQuery syntax, I have covered it in more detail in two previous posts: Using jQuery to directly call ASP.NET AJAX page methods and Three mistakes to avoid when using jQuery with ASP.NET AJAX.
Building and displaying the table
The page method’s JSON response is going to be similar to this:
[{"Date":"6/5/2008", "Title":"3 mistakes to avoid when using jQuery with ASP.NET AJAX", "Link":"http://encosia.com/2008/06/05/3-mistakes-to-avoid-when-using-jquery-with-aspnet-ajax/", "Description":"Three common problems that I've seen when using jQuery with ASP.NET AJAX, their underlying causes, and simple solutions to them."}, {"Date":"5/29/2008", "Title":"Using jQuery to directly call ASP.NET AJAX page methods", "Link":"http://encosia.com/2008/05/29/using-jquery-to-directly-call-aspnet-ajax-page-methods/", "Description":"An example of how to use jQuery to call an ASP.NET AJAX page method, without using a ScriptManager."}]
The anonymous type in our LINQ query comes through very nicely. The properties that we designated in the page method become keys in an associative array, making it easy for us to work with the data.
To build a table of this data on the client side, we can loop through each element, construct an HTML string, and then assign that string to a container’s innerHTML property:
function BuildTable(msg) { var table = '<table><thead><tr><th>Date</th><th>Title</th><th>Excerpt</th></thead><tbody>'; for (var post in msg) { var row = '<tr>'; row += '<td>' + msg[post].Date + '</td>'; row += '<td><a href="' + msg[post].Link + '">' + msg[post].Title + '</a></td>'; row += '<td>' + msg[post].Description + '</td>'; row += '</tr>'; table += row; } table += '</tbody></table>'; $('#Container').html(table); }
If you think that code looks ugly, that’s because it is. While it works great, I would not recommend this implementation. It will be difficult for you to maintain, and you’ll hope that anyone else forced to maintain it doesn’t know where you live.
Improving the situation with templating
The reason the former code is so ugly is that the presentation and logic are not separated. Even though this is all on the client side, separation of concerns is still an important goal to keep in mind.
To achieve separation, what we really need is a templating solution. As it turns out, there’s a great jQuery plugin called jTemplates, which is perfect for this application.
Using jTemplates, we can create a simple HTML template like this one:
<table> <thead> <tr> <th>Date</th> <th>Title</th> <th>Excerpt</th> </tr> </thead> <tbody> {#foreach $T.d as post} <tr> <td>{$T.post.Date}</td> <td><a href="{$T.post.Link}">{$T.post.Title}</a></td> <td>{$T.post.Description}</td> </tr> {#/for} </tbody> </table>
Since we’re focusing on disentanglement, this template belongs separate file. If we embedded in our JavaScript, we’d be taking two steps forward and one step back. In this case, I saved it as RSSTable.htm.
Note: I originally used the suffix .tpl for templates, but found that some versions of IIS will block access to them unless *.tpl is explicitly added as a valid filetype.
With the HTML template created, we can use a couple of jTemplates’ methods to apply the template to the container and then render the page method’s return.
function ApplyTemplate(msg) { // This method loads the HTML template and // prepares the container div to accept data. $('#Container').setTemplateURL('RSSTable.htm'); // This method applies the JSON array to the // container's template and renders it. $('#Container').processTemplate(msg); }
The rendered result will be identical to the previous, manual method, but the code is much cleaner. At this level of abstraction, I consider this method to be very similar to a client side Repeater.
Conclusion
This is a powerful optimization technique. Identifying overburdened UpdatePanels and replacing them with something like this yields massive performance increases. An order of magnitude isn’t uncommon, in my experience.
One of my sites, WinScrabble.com, was suffering from poor performance due to its primary feature relying on partial postbacks. Because the page was simple and had ViewState disabled, I thought the UpdatePanel would have a relatively minimal impact.
You wouldn’t believe just how wrong I was.
When I removed the UpdatePanel and replaced it with this technique, changing none of the underlying algorithms, requests for 7-8 letter searches ran over 400% faster. I have no doubt that you’ll be able to realize similar improvements in your projects.
In upcoming posts, I’ll go into detail about how to add some client side embellishments: Client side sorting, light-weight paging, and using CSS to improve upon the presentation. So, if you aren’t already subscribed to receive updates via RSS or Email, be sure to do so today.
Try it for yourself: download the source
Similar posts
What do you think?
I appreciate all of your comments, but please try to stay on topic. If you have a question unrelated to this post, I recommend posting on the ASP.NET forums or Stack Overflow instead.
If you're replying to another comment, use the threading feature by clicking "Reply to this comment" before submitting your own.
20 Mentions Elsewhere
- Dew Drop - June 26, 2008 | Alvin Ashcraft's Morning Dew
- More jQuery with Ajax/Json : { null != Steve }
- rascunho » Blog Archive » links for 2008-06-26
- 50 Excellent AJAX Tutorials | Tutorials | Smashing Magazine
- Favorite jQuery plugins compatible with ASP.NET « vincenthome’s Software Development
- 50 Excellent AJAX Tutorials | How2Pc
- Best Ajax Tutorials and Dynamic Solution for PHP ,Asp.net,Ruby On Rrails | Click On Tech
- 150 AJAX Tutorials » TemplateLite.com
- jQuery和asp.net mvc相关资源链接 - 自由、创新、研究、探索 - 博客园
- jQuery Sample – Others- 阿維實驗室
- uberVU - social comments
- 30 AJAX Tutorials For Smart Web Developers | Afif Fattouh - Web Specialist
- 30 AJAX Tutorials For Smart Web Developers « qeqnes | Designing. jQuery, Ajax, PHP, MySQL and Templates
- 30 AJAX Tutorials For Web Developers, Anyone! « Web Design
- 30 AJAX Tutorials For Smart Web Developers « Free PHP Scripts, js framework and ajax
- 30 AJAX Tutorials For Smart Web Developers | amazingtippo
- Microsoft support for jQuery « Reserved Words
- 40+ Extremely Useful Ajax Tools and Tutorials | WeDuggIt
- Microsoft support for jQuery | Reserved Words
- Visoft, Inc. Blogs | ASP.NET 4.0 AJAX – Preview 4 – Client Templates



Another killer article Dave. Nice work.
I am curious – you mentioned before you don’t use UpdatePanels and I see you have found a nice way to use PageMethods without the ScriptManager. So do you use any of the ASP.NET AJAX’s client side stuff? Or has it all been replaced with jQuery?
Matt.
Thanks, Matt.
I do still use UpdatePanels in some scenarios, where they speed up development and performance isn’t critical. In those cases, I’ll use ASP.NET AJAX’s client side events (pageLoad, BeginRequest, EndRequest, etc) in conjunction with jQuery.
That’s about it though. If I have jQuery on the page, I find that it’s much better suited to the presentational work.
Great Post!
Great article, Dave. I like the fact that jQuery is “in the game”.
Althought I was very eager to use UpdatePanels at first, I am very careful now :) My choice is rather calling script services from js.
I’ve too have discovered the jQuery-magic, but I use $.getJSON-method together with a WCF-service, and woaw, what a performance :-) I totally second your opinion in the performance, UpdatePanels are not fast enough.
However, I use the ugly way described above to create the client side html, but now you have presented jTemplates to me, and I will start refactoring at once ;-)
Looking forward to next interesting article!
This is just great, jQuery is a WOW,
Thanks for the posts dave, waiting for the next one.
This should be kicked hundred times Dave! You pointed me some great resources and usages of jQuery.
Great post after few weeks!
Keep it up
Hi Dave. Thank you for your article.
I have an application that uses WebParts and uses the drag and drop of controls with an update panel. For the dragging and dropping of controls in webparts is the update panel okay?
Do you have any articles about using jQuery a WebParts scenario?
My concern is that even if I have ms ajax for webparts with an update panel and I have a gridview that I need to update, it’ll use that update panel instead of jQuery. How can I separate it?
Thanks again for your article.
If you use the Gridview control it has to be processed on the server-side. Which means you have to use a postback to obtain the data of its state, so you would have to use an Update Panel to do this.
If you used a regular HTML table grid, you could update it with jQuery.
Great article!
I am implementing client side repeaters based off the article and I need some help with jTemplates but thier site has been down forever. Do you know where I can get some more information on syntax? Does it only have a for loop? I would like to have a section that states no data was loaded but I don’t know how to write an If statement or if it even has them. I know you are not the jTemplate keeper but no one else is writing about this stuff! Thanks in advance, Jason
There is an {#if} operator. Take a look in the “doc” directory in the jTemplates plugin download. It’s not ideal documentation, but might get you headed in the right direction.
I’ll make sure to add the “no results” case to my improvements in followup posts on this topic. Thanks for mentioning that.
Also my dates print out like this: /Date(1216259889000)/
Any ideas?
I am using c#, .Net, 2.0.
Thanks again,
Jason
Dates are a pain.
It’s not technically very proper, but I almost always convert them to a string on the server side (see the example above). For sorting and filtering, every JavaScript/jQuery plugin I’ve used is able to work with that correctly.
If true Date objects are needed, JavaScript’s Date.parse() is able to parse that format into Date objects.
I’m sure some would take issue with such a “lossy” method of dealing with the data, but I find it works well and is much more simple than the alternatives.
Your dates are printing out like that because you didn’t convert them to a string. You just parsed them as a DateTime.
Thank you for the quick and very accurate responses. I changed my dates to strings and I got the “if” statement working. This is what I used:
{#if $T.d.length == 0}
…
{#/if}
Worked great! Thanks again for the help!
Jason
On the /Date(12319000000)/ issue, I just posted something on Dave’s other http://encosia.com/2008/03/27/using-jquery-to-consume-aspnet-json-web-services/ post…
This ASP.NET DateTime JSON serialization issue I think I have a solution for. I outlined the solution as well as a regurgitated version of this original post at: http://www.overset.com/2008/07/18/simple-jquery-json-aspnet-webservice-datetime-support/
The solution is to pre-parse the DateTime JSON string response from the WebMethod/WebService before jQuery essentially eval()s it:
$.ajax({
// …
dataFilter: function (data, type) {
return data.replace(/”\\\/(Date\([0-9-]+\))\\\/”/gi, ‘$1′);
}
});
This works with jQuery 1.2.6 and .NET3.5 – but appears it might work with .NET2.0.
Schotime has also put a jQuery ajax() wrapper plugin together to help solve this: http://schotime.net/blog/index.php/2008/07/01/jquery-plugin-for-aspnet-ajax-jmsajax/
I am wondering if you left out a crucial line?
The above code never works for me because it has no idea what to do with “msg”
It only works with this line:
Am I missing something? I’ve spent about 2 days trying to get your example to work with no success.
Double check that you’re calling BuildTable(msg.d) in the $.ajax() “success” delegate, and not just BuildTable(msg).
Thanks. I understand your comment but that’s not the root of my question. I have never ever been able to work successfully with any javascript object created from a JSON string return without doing this first:
var evalMatt = eval(‘(‘ + msg.d + ‘)’);
Also, every single example on the net that I’ve found does that. Example: http://blog.platinumsolutions.com/node/91
What magic am I missing here that doesn’t require you to do an EVAL?
There’s no magic. JSON arrays are native JavaScript objects, so they don’t require any extra translation.
The eval() isn’t doing much there, but eval’ing msg.d has the side-effect of getting you closer to your data.
Have you tried this instead?
var matt = msg.d;
Great post. I have taken this example and applied to an application I am developing. I have run into an issue with jTemplates that I want to see if you have run into. I cannot get jTemplates to work hosted by IIS 6. I get a “expected ;” javascript error in jtemplates source. However in my dev environment hosted via VS or IIS 5 it works fine. Have you seen a problem with jTemplates hosted on IIS 6?
It works for me on IIS6, in IE6. Which browser are you using when you test it on IIS6?
Dave,
I am using IE6, IE7 and FF to view. I decided to host your example source and I get the same problem. I have it hosted on 3 different web servers all running IIS6. But your source still works hosted in IIS5. Any other thoughts?
Are any of those hosted in a location that I can view externally?
Did you ever find a resolution for this issue? I was getting the same thing and finally just gave up. Any ideas?
Darin’s issue was caused by his IIS6 configuration blocking the *.tpl extension.
The easiest workaround is to rename the template RSSTable.htm instead of RSSTable.tpl. Also, make sure to update the setTemplateURL call accordingly.
Thanks Dave, I’ll give that a try.
I just saw your new post about styling a table like this. I’ve been working on implementing this sort of client-side template with a table/grid as well, using the jquery.tablesorter plugin (and pager as well). I’m curious to see how you have tackled it – looking forward to your next post!
Make sure to download the source on my table styling post then. It already has jquery.tablesorter sorting implemented. I just didn’t have time/space to write about it in that post.
For some reason I can’t get it to find my externally defined template. If I define the template as a string and do the following then it’s fine:
$(“#ResultTable”).setTemplate(htmlTemplate, null, {filter_data: true});
However when I define VisitorLookup.tpl as an external file in my js directory then this blows up:
$(‘#ResultTable’).setTemplateURL(‘VisitorLookup.tpl’);
It fails on this line in TextNode.prototype.get:
var tmp = eval(__a1);
Any ideas?
It turns out that I needed to go into IIS7 and setup a Managed Handler as DefaultHttpHandler for the *.tpl extension. Unfortunately, this also allows users to download the templates if they guess their paths – but that is no worse than users being able to download js files.
Alternatively, if you don’t want to modify your server config, you can use .htm for the template’s extension.
Great tutorial but has it been covered how to provide a “loading” prompt whilst the script is retrieving the data? There is a slight pause before the table is drawn.
If this has already been covered then I apologise.
Great work, keep it up! Ian.
In most cases, I suggest using the technique shown in this post: http://encosia.com/2008/02/05/boost-aspnet-performance-with-deferred-content-loading/
The only caveat is that you must be sure to handle service call failure properly. You don’t want to leave an indefinite loading indicator if the call has failed.
Great article. Thanks for introducing me to jTemplates, it really does make the code more readable. Not a big fan of update panel asp.net AJAX stuff. So this is some really good stuff. Looks like everyone is taking a step to the other side(client side).
Hi Dave,
Just been trying this out and I’ve had a thought. Would it be possible to do this?
$addHandler(window, ‘load’, GetResults);
function GetResults() {
WebService.GetFeedburnerItems(10, OnResultsSuccess, OnPageFailed);
}
function OnResultsSuccess(result) {
$(‘#Container’).setTemplateURL(‘RSSTable.tpl’, null, { filter_data: false });
$(‘#Container’).processTemplate(result);
}
function OnPageFailed(error){
}
I tried it but I get an error about length being null or not an object. The reason I ask is that I like the templating but don’t want to use jquery everywhere…yet. I could use the microsoft datatable version but that’s nowhere near complete yet.
Cheers
Jon
You can definitely mix ASP.NET AJAX’s client side library with jQuery.
Try running that in Firefox with Firebug, to get a more specific location for the JavaScript error.
The .tpl extension has caused trouble on some versions of IIS. You might try renaming that file to .htm. That’s just a shot in the dark, but a failure to load the template might result in a null length error like you’re seeing.
Dave,
Have looked at this using firebug and there seems to be a problem somewhere in the jtemplate processing.
Here’s my code:
The message I get is fcount is undefined:
fcount is undefined
(?)()()3DYR8yd%…e3Q%3D%3D (line 1)
(?)()()3DYR8yd%…e3Q%3D%3D (line 1)
(?)()()3DYR8yd%…e3Q%3D%3D (line 1)
nodeName()()jquery-1….6.min.js (line 21)
filter()()jquery-1….6.min.js (line 12)
(?)()()3DYR8yd%…e3Q%3D%3D (line 1)
ApplyTemplate(Object 0=Object)Default.aspx (line 89)
l()ScriptRe…f971dc229 (line 5)
createCallback()()ScriptRe…f971dc229 (line 5)
createCallback()(Object)ScriptRe…f971dc229 (line 5)
createCallback()()
Which doesn’t help. I’ve done some searching but can’t find anything on it.
Jon
In your template, are you using $T.d like I did in my example above? If so, try it with just $T there.
Using $T.d with MSAJAX would basically be like trying to reference msg.d.d instead of msg.d.
If that doesn’t help, I’d suggest setting a Firebug breakpoint in your ApplyTemplate function and inspecting the value of msg.
Dave
That’s an awesome answer!
It worked first time.
Thanks for your help
Jon
Dave,
I am using Visual Studio 2005 / .NET 2.0.
I recently discovered JQuery a couple of weeks ago. I came across your blog which has been a great help in using this with .NET.
I am new to JSON as well.
Question: I am not using .NET 3.5 is that why I get undefined when trying to use msg.d? It works fine without
the .d.
Question: I was also getting fcount is undefined. Firebug showed the response to be the correct json output from
the page method.
I than decided to alert(msg) and it return a string instead of “[object Object]“.
I found a few threads on google stating you have to eval() the string to make into a object. I finally got the JTemplate to work
after that.
I want to make sure that I am doing this in the correct manner and that eval is the right approach.
That’s making it a bit more difficult than it has to be.
ASP.NET AJAX will JSON serialize your data automatically. So, when you return a string of JSON, you’re sending back msg.d.stringOfJSON instead of msg.d.yourDataStructure.
Ideally, you should return that data directly, to avoid manual serialization and double eval()’ing on the client side.
Dave,
I just came across an article that used generic dictionary’s to store the information inside the datatable:
http://schotime.net/blog/index.php/2008/07/27/dataset-datatable-to-json/
That greatly simplified it and allowed me to return the generic data structure:
I didn’t have to eval() and was able to use the Template with {#foreach $T.tableName as row}
Very cool!
I am still learning how this all works and was using Update Panels. I started learning JQuery a few weeks ago and stumbled across your site. Thank you for all these great articles and your quick responses to comments.
That’s a good improvement. It’s definitely better to let ASP.NET AJAX handle the JSON serialization when using ASMX. That conversion method isn’t necessary though.
In that situation, I’d probably set the return type of the web service to List and return that collection directly. If that’s not feasible, you can always add the DataTable to a DataSet and return the DataSet (it will serialize a DataSet to JSON automatically).
Dave,
I added the DataTable to a DataSet and when I returned it firebug response showed:
{“Message”:”A circular reference was detected while serializing an object of type \u0027System.Globalization
.CultureInfo\u0027.”,”StackTrace”:”…
I chose to do a generic list and built a quick inner class for it. This works and was able to iterate through with the JTemplate.
Everything I’ve tried though still returns undefined when I try to do msg.d. For now I’m using msg and it works fine.
Is that because I’m on .NET 2.0?
Thanks for your tips and I hope I’m going in the direction now.
The generic List sounds good to me. I usually use either List or IEnumerable for JSON return types, and have had great results with those.
That’s correct about 2.0 and msg.d. The .d was added as a security feature in 3.5, to prevent potential XSS exploits due to malicious user input.
Just keep in mind that you’ll need to add the .d if you upgrade to 3.5.
Dave,
Thank you for all your help. I understand so much more now. I didn’t realize my work already renewed our MSDN. So I updated to VS 2008. I liked your LINQ example above and sure enough it was as simple as this:
I orded LINQ in Action and JQuery in Action for some fun reading.
This is great stuff and so is your site.
Hi Dave…again
It seems like you are the only source of good information, apart from maybe Rick Strahl, on jquery on the internet.
Is it possible, to your knowledge, to insert html into a jtemplate?
i.e.
How would you insert HTML into the below placeholder, at the moment it just renders as text. Or are jtemplates simply not designed for this and shouldn’t be used in such a way?
{$T.property.HTML}
Cheers
Jon
jTemplates has HTML filtering functionality enabled by default. You can turn it off when you “set” the template, like this:
Brilliant as ever.
I assume that if I have a List within a List I can do nested {#foreach} within the template?
PS: Where do you get all your jtemplate info from? Or is it all experimenting?
I haven’t tried the nested case, but I believe that’s possible.
Mostly experimentation, and reading through the docs/code for the plugin. You can usually figure out the broad strokes about jQuery plugins from their code, quickly.
Jonathan,
I was needing to do nested {#foreach} as well in the template.
I can confirm that it is possible.
I did it with returning IEnumerable
Inline JTemplate:
Hi Michael,
I did try it myself, it seemed quite simple in the end. Thanks for showing the code though, hopefully it will help a few people…and a reference for me in case I forget it all!
Cheers
Jon
JTemplate is so cool and as time goes I figure more out. I had an issue that I wanted a outer foreach value to be repeated in one of the nested foreach statements.
You can do this by setting a param like:
{#param name=TeamID value=$T.row.TeamID}
You can than get to that current value inside the nested foreach:
{$P.TeamID}
Hope this helps others.
Hello Dave. Great Blog! I have tried using jQuery to invoke a WCF ajax service using your exact code above; however, I receive a ‘parseerror’ on the error callback function’s status parameter. Debugging the server-side WCF service show the code executing correctly; however, client-side receives no data and invokes the aforementioned error callback. I’ve Googled to no avail. What am I missing? Thanks… -Dan
If your WCF service is configured to support it, you can replace that $.ajax() call with $.getJSON(). Most of the complexity of that $.ajax() code is specific to ASMX services.
Also, you’ll want to replace “$T.d” with just “$T”. The “.d” is also something specific to ASMX services.
Thanks Dave. I tried everything to request the WCF service call over POST, but couldn’t get it to work; however, after decorating the WCF service method (e.g. [WebGet(ResponseFormat=WebMessageFormat.Json)]) and creating a DataContract decorated Item Feed class, I got it to work, but over GET. Beyond the caching issue, do you recommend GET or POST, or whatever the flavor of the day? Thanks again… -Dan
The reasoning behind the ASP.NET AJAX serializer only providing JSON for POST requests is that it’s a higher barrier to easily poking around at the service in a browser. Obviously, if someone’s determined to do that, they can send spurious POST requests instead.
In the end, providing JSON via GET isn’t inherently a problem. Just keep in mind that potentially malicious users may craft their own GET requests to your service, and don’t rely on your client side functionality being the exclusive gatekeeper to that service’s interface.
I was wondering how I might make a repeater like yours but that edits multiple records at once and how I would loop through them using jquery? Maybe have a custom attribute that sets the primary key? I must admit I’m spoiled with the asp.net repeater. I’ll play around with it and post if I come up with anything.
I’d suggest a hidden field in your item template for the PK.
To flag particular rows as having been edited, you can use a dummy CSS class to flag them as they’re manipulated. Maybe an “editing” and “edited” class.
Then, it’s easy to construct a selector to iterate over the desired rows, extract the PK field’s value, and take some action.
I’ve modified this example to create a search type interface. In IE7 it appends a new table to whatever already exists in the Container div tag whenever ApplyTemplate is called. In Firefox it just replaces whatever was in there with the new table, which is the behavior I want. I tried a few things in order to remove the appending of new tables, but nothing has worked.
I tried to clear the html from the container div by calling the html() method and passing in an empty string, but that didn’t work.
function ApplyTemplate(msg) { $('#Container').html(""); $('#Container').setTemplateURL('table.tpl', null, { filter_data: false }); $('#Container').processTemplate(msg); }I’ve also tried empty() which did not work either.
Dave,
First, I want to thank you for providing these excellent example of jQuery, AJAX and ASP.Net. Each of these are new to me, but with your help I’m learning a lot.
Second, I have what I think is a simple question:
I have a function that accepts multiple parameters (imgbtn_id, imgbtn_alttxt), but in your example “{‘Count’:’7′}” you pass a single parameter. What syntax do I need to use to pass multiple parameters?
In your specific example, it would be:
"{'imgbtn_id':'foo','imgbtn_alttxt':'bar'}"Check out http://json.org for a comprehensive guide to forming JSON arrays.
Thanks for the quick reply, Dave.
Based on your example, I’m using the following syntax in my jQuery code:
data:”{‘imgbtn’:'” +imgbtn_id+ “‘,’bckgrnd’:'” +imgbtn_alttxt+ “‘}”,
Function:
_
Public Shared Function
setBackgroundImage_OnClick(ByVal imgbtn As String, ByVal bckgrnd As String) As String
‘Do stuff
End Function
Using Firebug, I can see that the jQuery function dies as soon as it hits the data: (see above) line.
Any ideas what may be wrong with my code?
That looks correct to me.
Is it dying with a JavaScript error or a 500 error back from the server?
Are you sure those variables are defined? You might want to set a breakpoint on the “data” line in Firebug and verify their values.
When it dies at the data: line, I receive no error message.
Make sure your Shared Method you are calling in VB has the attribute [WebMethod] or the server will return a 500 error back. It’s response would contain: Exception Details: System.ArgumentException: Unknown web method..
Sorry, [WebMethod] is C#. Use <WebMethod()> _
This is a real head scratcher. The jQuery code worked fine when the
only had one parameter, but as soon as I added the second parameter it began failing on the jQuery data: line. Using Firebug, I verified that both variables are being properly set.
I know you’re very busy and I don’t want to monopolize your time, but I thought that I’d post more of my code in case you could spot a problem:
******jQuery****** $(document).ready(function() { $("#ImageButton1").click(function() { var imbt_alttxt = $(this).attr("alt"); var imbtn_id = $(this).attr("id"); $.ajax({ type: "POST", url: "jQueryPageMethod.aspx/setBackgroundImage_OnClick", data: "{'imgbtn':'" + imgbtn_id + "','bckgrnd':'" + imgbtn_alttxt + "'}", contentType: "application/json; charset=utf-8", dataType: "json", success: function(msg) { $("body").html(msg.d); } }); }); }); ******ASP.Net****** ******WebMethod****** _ Public Shared Function setBackgroundImage_OnClick(ByVal imgbtn As String, ByVal bckgrnd As String) As String 'Do stuff Return "foo" End FunctionAs stated before, the jQuery code fails at the data: line so the
never gets called.
Again, I really appreciate your input.
Is it possible that either of those variables contains unescaped quotes or apostrophes?
Based on a question you posed, I did catch a typo in one of the variables.Now the jQuery code executes all the way to the success: line, but then fails.Is there some way for me to trap the error message?
Would you mind showing me how I should construct an error handler so that I can see where it’s failing?
Ty,
You can use the error in your jquery ajax to show the failed response from the web server. The following outputs into an alert message, but you might want to output to a element in your page.
Note: If you are using FireBug you can click on the Net tab. Expand the POST method and look at the RESPONSE. It will show what the server posted back.
Hope this helps.
Dave/Michael,
I wanted to thank each of you for your assistance. With your advice and coding samples I was able to track down and correct the error! The code is now working great.
Best Regards,
Ty
quick question
how do i get the index for the current item in the jTemplate loop
from your example above :
{#foreach $T.d as post}
i need to get 0,1,2,….
post object index ?
–thanks
Try $iteration, like so:
works Great, Thanks Dave.
Hello!
Thanks for a great blog post! I just have a thought, can I use this with User Controls as well? I really need to do that.
Greetings from Sweden!
While using jTemplates in the template file either tpl or htm i am having a simple html input button i want to attach a jquery button click event to it so that every button when rendere will have that.how can i attach that when i attach it on my aspx page i think it will not find the button object because i will load it after calling the page method when the template is rendered, so initially there is no button on the page.
My question is where i have to attach this event handler have i to attach it inside the sucessfunction or simply on the page or on the template.
Hi Aashish,
If you are dynamically building the buttons than you should use a class on the button instead of an id.
<input type="button" class="myButton" />In your javascript do a JQuery selector:
This is a basic example, but this would be what you need to do. JQuery will add the click event to all the buttons with that class.
I have came efficient with JTemplate and have commented about it throughout this thread. As I started to do more complex JTemplates it started to look really messy.
I started to switch to John Resig’s Microtemplating: http://ejohn.org/blog/javascript-micro-templating/
Rick Strahl modified it slightly in this article here: http://www.west-wind.com/Weblog/posts/509108.aspx
I recently found the following Template solution that keeps all logic out of the HTML markup and relies on classes. I have converted many of my JTemplate’s with extreme ease.
The author is very responsive with resolving issues.
Take a look at this templating solution and I think you will be impressed: http://www.beebole.com/pure/
I’ve actually looked at Pure in the past and it looks very promising. I’m going to give it a try on one of my sites, to get a feel for it in practice.
I do wonder how much complexity managing class name collisions would add on a real-world project though. Designers and developers would have to tip-toe more carefully around that overlap between presentation and functionality.
Dave,
I agree that careful thought will need to be taken into consideration to the designer. Removing specific classes that would be needed to populate the templates would break. Might mean for bigger projects making comments into the CSS rules at the top that the following class names must remain even if not styled on.
With Directives though you can do a lot of cool things and I prefer that over basic examples shown in pure where you can do something like:
<a></a>I prefer the directive to map property to a normal class than using @ in the class name.
But great stuff. I am still playing with it and like it so far.
Dave,
Thanks. I already figured out the problem.
For and with ids, HTML with add sorted number at the end of the id.
In order for me to set up or get value for/from and , I have to use “contain”
$(“#RSSTable”).each(function() {
$(this).find(“#RSSTbody”).each(function() {
$(this).find(‘tr[id*=RSSTr]‘).each(function() {
$(this).find(‘td[id*=CalendarEvent_EventDate]:contains(‘ + todayDate + ‘)’).css(‘background’, ‘yellow’);
});
});
});
Anyone seen this problem before. A template runs fine on my dev machine, runs fine on the live machine when viewing in FF but not in IE8
$(‘#autoSuggestionsList’).setTemplateURL(‘/Modules/TableTemplates/LocationsTemplate.htm’);
$(‘#autoSuggestionsList’).processTemplate(msg);
I get a message saying:
Error: Object doesn’t support this property or method
For some reason the setTemplateURL doesn’t seem to work.
@Jonathan
Instead of using setTemplateURL try using
$(‘#autoSuggestionsList’).setTemplate($(‘#yourTemplateName’).html,
null,{filter_data:false});
$(‘#autoSuggestionsList’).processTemplate(msg);
and include your template on the page itself like this
<script type=”text/html” id=”yourTemplateName”
You can get some help from this link
http://smallworkarounds.blogspot.com/2009/02/jquery-aspnet-how-to-implement.html
If this also doesn’t solve your problem try analysing your template html it might be breaking somewhere or not in accordance to some crapy standards for which IE would be crying
Hope this helps
Aashish Gupta
Great post. i like your posts.
Dave,
I’m new to linq and I ran into some trouble using it in a web method today. I wrapped my method in a try..catch block and deliberately broke the code within the linq statement to test the exception handling that I had set up, but the catch statement never executed. I discovered that it was because the exception was being included in the anonymous type that was being returned to the browser. I discovered that accessing the anonymous type before returning it to the browser caused the exception to be raised. So I came up with this solution in order to force the exception to raise properly rather than remain embedded in the return value…
It seems like a hack and I’d be happy to know if you have a better solution to the problem. If not, perhaps this solution will be beneficial to your readers.
Additional testing has revealed that calling
will cause problems if there are no results. A possible alternative is to call
This causes an exception in the anonymous type to be raised and isn’t adversely affected by an empty set.
Anyone have better ideas?
I’ve been studying Linq trying to better understand what is happening here and I think I can explain the problem better now. The problem I was experiencing is due to deferred query execution which means that this line…
…is not evaluated until the feeds var is actually enumerated. The enumeration occurs outside of the scope of the web method (when asp.net serializes the result to be sent back to the client) and thus cannot be caught within the web method.
This forum post contains a response by Matt Warren, one of the designers of Linq at Microsoft. He offers a suggestion for dealing with this in which he recommends calling ToList() on the anonymous type in this fashion:
This causes the anonymous type to be enumerated immediately resulting in the expected exception being thrown.
I cannot access the contents of the RSS feed.
I get an exception;
“The underlying connection was closed: An unexpected error occurred on a receive.”
and an inner exception;
“Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host.”
That probably means there’s a network related issue between where your server-side code is running and where the RSS feed you’re trying to consume is hosted.
Hi Dave,
I’m a newbie in jQuery, How do you make a editable/updatable table like in gridview?
do you have any article for that?
best regards
While you’re still acclimating, it’s probably not a good idea to write something that complicated from scratch. I’d suggest checking out either the DataTables or jqGrid plugins.
Hello Dave,
Your code is awesome. I like the idea of implementing the ASP.NET repeater functionality at the client side . But I need to implement one more feature which ASP.NET repeater have -ItemDatabound.
In your code:
Date
Title
Excerpt
{#foreach $T.d as post}
{$T.post.Date}
{$T.post.Title}
{$T.post.Description}
{#/for}
I need ItemDatabound feature say :
I need this
GetFormattedDesc({$T.post.Description})
GetFormattedDesc is server side method which process the the Description and brings the formatted output.
Can it be possible to do ItemDatabound like feature in above example which you have provided.
Raghav,
I see two options for you in this case.
1) Perform your manipulation in your webmethod before the data is returned to the client. Something like this:
2)Convert your server-side GetFormattedDesc() method into javascript and call it client-side…
Calling a method on the server requires a web method and would be inefficient in a repeater-type situation.
Hello Joel,
Thanks for your reply.
Me Web Method(It is in web service) will be like:
[WebMethod] public IEnumerable GetUserArticles(int param1,param2) { return EntityManager.FindRecords(arg1,arg2..); }I am returning the collection of Entity Class objects to Client side. I don’t want to apply methods like ‘GetFormattedDesc’ here as My Client side repeater control will be used at many places, so I would not like to impose operations here. I would leave on the user end who will implement the repeater to use server side method on a column say description here.
According to the your second suggestion I did this:
{#foreach $T.d as post} <li><a href="{CreateUrl($T.post.ID)}" rel="nofollow">{$T.post.Headline}</a> </li> {#/for} function CreateUrl(id) { //do logic return "http://www.ggogle.com"; }But no success the href is rendering as it is:
{CreateUrl($T.post.ID)
How can I get the URL Bind dynamically for each row as I was doing in my ASP.NET repeater.
In ASP.NET I was able to do like this way:
It looks like your template isn’t being properly expanded at all. I can’t tell why not from the code you’ve provided, unless the missing closing brace is actually missing in your template…
That was my fault. WordPress ate his comment due to the unescaped HTML. I temporarily escaped it to get the comment through and edited it back. It should be correct now.
Unless the formatting significantly increases the size of the data you’re sending, I’d agree with Joel’s first suggestion. That’s the approach I use most of the time myself.
Dave,
thanks for writing this article. I am .Net developer and loving what this article has taught me about JQuery.
Question:
I am trying to implement the following functionality:
With asp.net repeater it will allow me to use a linkbutton like this:
<asp:LinkButton OnClick="LinkButtonDelete_Clicked" CommandArgument='’ ID=”LinkButtonDelete” runat=”server”>
I could then implement the method LinkButtonDelete_Clicked() event on the server side and capture the Object’s ID from the commandArgument and Delete that particular record from the database.
I need that exact functionality with the client side repeater where i can call a web service to delete a record from the repeater.
Any help is appreciated.
I often embed the IDs into table rows with expando attributes. In this post’s example, maybe something like this in the template:
Then an event handler like this could act on those delete links:
wow… this works like a charm. Precise answer with solution lol, thanks alot!
Hi Dave,
I have one question in gridview we have one event say onrowdatabound where we can manipulate our grid according to data. say i have one column named detail which conatain one link button so if count will come then only i will enable it other wise i will disable that link button. This kind of activity we do in onrowdatabound. Is there anything in jtemplate to implement onrowdatabound things?
You can achieve similar effect by embedding functions within your templates. The jTemplates site has an example of that under “Using functions” on this page: http://jtemplates.tpython.com/
Another option would be to use the {#if} syntax within your template to conditionally render the anchor element (or only conditionally render its href attribute, to get the “disabled” effect).
Hi Dave
Firstly, outstanding article – I especially liked the addition of jTemplates and have started using them since reading this. Thanks.
I wonder if you’ve tried something – I’m trying to load my template into a modal popup of some sort (currently I’m trying with Colorbox but I have no real preference, this is the first one I’ve tried). I’m struggling to get the process looking slick because of the way jTemplates is swapping the content of my empty div. I’m using the option of loading ‘inline’ html into the popup.
So, the question is – have you used a modal plugin with jTemplates successfully before? a preloading message whilst the ajax call was in progress would be great!
Thanks, Stu
P.S I can post some code if that helps
Stu,
I haven’t used JTemplate in a while, but you should be able to do what you want with colorbox plugin.
I’ve used in a project where clicking on map region would bring up a modal that would load programs. I just did the html appending through JQuery so didn’t use any template, but here is some code:
onOpen function calls:
HTML Exmaple:
Another thing you could do is call colorbox function after your ajax call completed like:
//
// show video
$.fn.colorbox({options});
Now when modal comes up it shows the ajax progress, but I don’t think the progress is throughout the whole ajax request. So you will have experiment to see which way is better to use colorbox..
That is about as helpful as I can be as far as using color box in a few projects.
Thanks Michael, I’ll give that a go!
I m getting error length is null or not an object.
My code is
The web method is
Please help me..
Thanks
@kunal – forgot to hit reply. See below
@kunal
Have you tried
success: DrawWorldMap(data.d)
That should be where you find the JSON response data…
or perhaps more accurately,
success: function(data) {
DrawWorldMap(data.d)
}
Yes Sir,I did changes..It gives error, d is null or not an object at alert statement
Thanks
Kunal,
Glancing at your code.
data.d contains your object that you are passing DrawWorldMap.
You are than doing:
Your response most likely does not have a property d, so you should just alert response.
Your object graph will probably be the following:
response.countries[0].Country
response.countries[0].Popularity
You should install Firebug plugin for FireFox browser for it will show you posted values and response. You would quickly resolve these issues using that tool.
Can you tell me which type of project should i select from project menu.. I am new to .net,i am using visual studio 2008
@kunal
Okay – I’ve made the following sample and it works on my machine:
Code-behind: (.aspx.cs)
Your page (remember to include jQuery scripts):
If you’re looking for fundamental help with Visual Stuio – I’d recommend making a cup of tea and starting here: http://www.asp.net/LEARN/videos/
Stu
great post…this is what i looking for..really thanks…
nice article buddy
Great script, just stumbled across it
For some reason I can’t get it to work on my Firefox4. It doesn’t load the table, how do i backtrace to the error? no error are shown on my firebug, and it works great on my chrome
Sorry this was meant for the pagination topic, your sample works great, but my modified does not
If there are no JavaScript errors in the console, the next step would be to use Firebug to set a breakpoint near where you think the problem might be. When execution is paused there, you can take a look at what the variables actually are and make sure the values you expected are what comes back. For example, in the code above, I’d probably set a breakpoint in the
successhandler and go from there.Hi everybody,
I am working with jquery and .net in scenarios similar to this example.. in my local development computer all works fine.. but when i pusblish to the production web server the ajax doesn’t work.. always get the error: 200 OK… reading the documentation talks about of Cross domain policy… but i dont call mathods out of domain… like this sample i call a method in my own aspx page…. So i dont understand the problem….
Do you know why i present this behavior?
Note: If i use cross domain calls the solcution is use jsonp or other weird things… but i dont want use this tecniques because is simple that i want to do…. :(
Make sure the URL in your
$.ajax()method is a relative URL (doesn’t contain the HTTP://). Absolute URLs sometimes cause jQuery 1.5+ to treat them as cross-domain requests.I had a lot of problems getting the service to crack out JSON objects. I found a solution http://encosia.com/using-jquery-to-directly-call-aspnet-ajax-page-methods/
Forgive me if I dont get it but it seems to me using a table is the desired means to create a template. I have an excisting template where a table is not being used. I will want to keep what I have for layout reasons is this going to possible.
<pre lang="
<div class="repFocus float_left ">
<div class="repImgContainer float_left">
<asp:Image ID="Image1" ImageUrl='<%# Product.ImagePath %>' runat="server" Height="<%# Product.GetHeightByImageSize(EnumImageSize.Thumbnail, MaxImageHeight) %>"
Width="<%# Product.GetConstrainedWidthByImageSize(EnumImageSize.Thumbnail, MaxImageHeight) %>" />
</div>
<div class="repTxtContainer float_right">
<ul>
<li>
<asp:Label ID="nameLabel" CssClass="repName" runat="server" Text="<%# Product.Name %>" />
</li>
<li>
<asp:Label ID="Label2" CssClass="replabelTxt" runat="server" Text="From "></asp:Label>
<asp:Label ID="priceLabel" CssClass="repPrice" runat="server" Text='<%# String.Format("£{0:f2}", Product.Price) %>' /></li>
<li>
<asp:Label ID="sizeLabel" CssClass="repSize" runat="server" Text="<%# Product.Size %>" />
<asp:Label ID="Label1" runat="server" CssClass="replabelTxt" Text=" and Up"></asp:Label></li>
</ul>
</div>
</div>
</div>
">code
If I manage to get my head around to using your approach it will be great in the long run.
Thanks!
Using a table isn’t necessary. I only used one here because the end result I wanted was a table. You could definitely use a template to render the
<div>and<ul>structure you’re currently using.I am using .net 2.0 .How i can implement jquery in .net 2.0 as LINQ is not a part of .net 2.0. Please help me.
LINQ isn’t necessary for making the
$.ajax()call or for using jQuery with ASP.NET. It’s only needed in this example because I’m using LINQ to XML to parse data out of my blog’s (XML) RSS feed.Thanks Dave for your reply.
I am very new to jquery so can you explain with a example to help me.
The LINQ stuff isn’t necessary or related to getting jQuery to work with ASP.NET. Just do whatever server-side work you need to in the method, instead of using LINQ to XML.
If you’re new to using jQuery with ASP.NET, go through this list of posts: http://encosia.com/jquery-for-the-asp-net-developer/
Hi Dave, I’ve been using jTemplates for awhile, and trying to build a site completely with jQuery + jTemplates + Web Services. Things worked out really great until i stumbled upon a situation like this, where i need to add some server control or need to resolve some data from the code behind using code block in the midst of template rendering.
Consider the stripped down version of jTemplates below:
<script type="text/html" id="ContentTemplates"> {#template MAIN} {#foreach $T.Products as product} <div id="div-product-{$T.product.Id}" class="product-wrapper"> {#include Content root=$T.product} </div> {#/for} {#/template MAIN} {#template Content} <div class="view-container"> <p>Id: {$T.Id}</p> <p>Desc: {$T.Desc}</p> <p>Vendor Id: {$T.VendorId}</p> <!-- Vendor name doesn't supplied by the web service, it needs to be resolved using ASP.NET server code <p>Vendor Name: <%= GetVendorName({$T.VendorId}) %></p> i was hoping to do something like this, but apparently it wouldn't work this way --> </div> {#/template Content} </script>Now i’m banging my head on the wall for failing to achieve something as easy as this.. is it something that I’ve missed? or is it that jTemplates really should be used to render simple HTML layout only? Is the template engine capable of resolving server code blocks? Or am I simply just DOOMED?
I’m already started to convert my code from client-side to server-side now. Nonetheless, I hope there’s good news from you, bcoz I really like to stick with current design and I think they’re just COOL!
You won’t be able to render the server-side variable directly into the client-side template. They’re being rendered at different times, so the best you would be able to do is render a single vendor name that would be used for every iteration on the client-side (which I don’t think is what you want).
You should still be able to get this into the client-side data. Either try to pull it into your products collection, or render that collection into the page as JSON and then merge it into “products” before rendering the jTemplates template.
great. but is it possible nested template. something like this:
<tbody> {#foreach $T.d as post} <tr> <td>{$T.post.Date}</td> <td> <a href="{$T.post.Link}">{$T.post.Title}</a> <!-- Nested jtemplate --> {#foreach $T.d1 as post1} <div>{$T.post1.Date}</div> {#/for} </td> <td>{$T.post.Description}</td> </tr> {#/for} </tbody>