punkish has asked for the wisdom of the Perl Monks concerning the following question:

Gentlemenk,

I wrote a reasonably complicated HTML:Template-based web application that works fine. Now, I want to insert some XMLHttpRequest functionality. I've got the skeleton code working, however, I can't for the life of me figure out how to merge it with HTML::Template. Here is the pseudo-flow of the application --

### in my code my $foo = $cgi->param('foo'); # do a bunch of things with $foo, # get data out of SQLite, # prepare html output, print "Content-Type: text/html\n\n", $template->output; ### in my template <TMPL_LOOP FOO> <TMPL_VAR BAR><br> </TMPL_LOOP>

But, now I've added the XMLHttpRequest code to the template so 'foo' is sent to the server in background, so to say. However, I can't output the entire $template anymore... I have to output only the resulting recordset, receive it back at the client's end, process it and output it using innerHTML to create the same pretty output that I was getting with TMPL_LOOP. The best I can figure is --

### in my code my $foo = $cgi->param('foo'); # figure out if XMLHttpRequest if ($foo) { # do a bunch of things with $foo, # get data out of SQLite, # prepare XMLHttpRequest output print "Content-Type: text/html\n\n", $output; # for all other normal cgi requests } else { # grab cgi params, # do a bunch of things with them, # get data out of SQLite, # prepare html output, print "Content-Type: text/html\n\n", $template->output; } ### in my template, # document.getElementById("output").innerHTML = output; <div id="output"></div>

Well, isn't that terrible? I've just gone and messed up my neat H::T based View and Controller separation. Is there a cleaner, better, more satisfying method?

--

when small people start casting long shadows, it is time to go to bed

Replies are listed 'Best First'.
Re: integrating XMLHttpRequest and HTML::Template
by mpeters (Chaplain) on Jun 03, 2005 at 14:48 UTC
    I think you need to split off you templates into smaller pieces. The pieces that can be requested via XMLHttpRequest should be in separare templates. Then you can look at some query param in the request (maybe named 'ajax'?). If it's present, just process the smaller requested template. If it's not, then process the smaller template and then wrap it inside of a larger site template. This is easier to do with Template Toolkit since it has the WRAPPER functionality, but you might be able to accomplish something similar with if/else includes.
    <tmpl_unless ajax> <tmpl_include header.tmpl> </tmpl_unless> <!-- some mark up requested by the browser --> <tmpl_unless ajax> <tmpl_include footer.tmpl> </tmpl_unless>

    More people are killed every year by pigs than by sharks, which shows you how good we are at evaluating risk. -- Bruce Schneier
Re: integrating XMLHttpRequest and HTML::Template
by cees (Curate) on Jun 03, 2005 at 14:26 UTC

    The whole point about separating your code into a View and a Controller is not to lock you into always using templates for your View. Templates are only one way of implementing a View.

    The point of the separation is so that you can easily adapt your code to provide alternate Views! In this case your View is actually running in the browser, so your Controller can push the data directly to the browser, and you use some JavaScript to display the information. An other View could be a CSV dump of the data, or an XML dump, or you could provide a WAP interface. Some of those may use templates for the View, but they certainly don't have to.

      in other words, are you saying that what I am doing is fine, and there may not be a better way? ;-)

      For example, I could think of possibly separating my cgi code, so the H::T code is in one file, and the XMLHttpRequest code is in another.

      --

      when small people start casting long shadows, it is time to go to bed
Re: integrating XMLHttpRequest and HTML::Template
by cfreak (Chaplain) on Jun 03, 2005 at 14:46 UTC

    You're on the right track for doing simple stuff. You just prepare your document as normal. HTML::Template doesn't care if your template is really only a partial page. Really the only reason your CGI should even care if you have an XML request instead of a normal page load is if the output is different (and really you could set that up in the template itself)