Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Good DRY approach to rendering and AJAX updating of page

Tags:

jquery

ajax

Imagine a review site where users enter ratings and optionally short comments.

On each review page you've got many comments - these are displayed in a table at the end of the page (btw - not looking for datagrid type controls, far too simple for that)

I want to let users enter new reviews and update the page without a page refresh.(all simple stuff so far, this is not the question)

What is a good approach to generating for the page. Some thoughts :-

  1. Generate the reviews HTML server side, append new reviews using javascript client side. Downside is that you've got table HTML generation code in two places. Upside - more content on page as far as search engines concerned.

  2. Server side only output reviews as json/xml/whatever and render HTML dynamically on page load using javasript.

    Downside - 'template' in javascript, hard for designers to customize + lack of 'content' on page.

  3. Is there an approach that combines the two methods - i.e. a templating framework that will render existing data server side but also sends the template fragment client side so it can be reused there for additions/edits.

  4. With (2) to get the data on initial page load would you

    • a) include json/xml on initial page and run client side render on page load

    • b) get it via a separate AJAX call on page load (+ simpler, - extra request and delay)

I am focused on jQuery/Django but this question applies to other frameworks and AJAX libraries.

This is a bit of a subjective quesiton, hope it doesn't step over the line! Thoughts?

like image 681
Ryan Avatar asked Mar 01 '11 13:03

Ryan


2 Answers

With a framework, an approach to your scenario (3) -- combining both methods -- is to use a view "partial". A partial is a fragment of a view that can be rendered on its own; a single view could be made up of several partials.

In your case, you'd define a partial to render a review. When showing the page from scratch, the server-side code loops through existing reviews and calls the partial to render them one after the other. When a new review is added to the existing page, the javascript asks the server to render just the partial for that new review and return it as an Ajax response, and then appends it to the existing reviews on the page.

like image 190
Matt Gibson Avatar answered Oct 23 '22 00:10

Matt Gibson


You wouldn't necessarily have to know the template ahead of time, you'd just have to set hooks in the code for what data you want to fill in with JSON when you render your template.

The scenario would work like this:

  1. Server side generates the page on initial load
  2. AJAX call finds new page data and wants to render it
  3. jQuery clones comment item from the page and re-populates the data with JSON

I personally like keeping initial page load on the server-side for making it easier to cache pages and then only use AJAX for when you need to update the page or switch to a related page without the website having to reload.

An example for you:

<ul class="commentsArea">
    <li class="comment" data-commenter-id="user1234">
        <a href="#" class="userName">Rob</a>
        <p class="userCommentContent">Some comment content would go here.</p>
    </li>
</ul>

Then you'd have a templating function:

function template(comment, newCommentMetaData) {
    // comment is a cloned comment object
    // newCommentMetaData is the AJAX data
    comment.attr('data-commenter-id', newCommentMetaData.userid);
    comment.find('.userName').text(newCommentMetaData.name); 
    comment.find('.userCommentContent').text(newCommentMetaData.content); 
    return comment; 
}

Then finally you'd have to clone the comment to add new ones:

var newComment = $('li.comment:first').clone();
// fill in your AJAX data here
var newCommentMetaData = {
    userid: 'user2345',
    name: 'Pete',
    content: 'The new comment content goes here'
};
/* you would have to put an each() function here to iterate through all new comments
   and template them up, but hopefully you get the idea */

template(newComment, newCommentMetaData).appendTo('.commentsArea').fadeIn();
like image 44
iwasrobbed Avatar answered Oct 23 '22 00:10

iwasrobbed