AJAX in Contao

In this article you will find out how to use Asynchronous Javascript And XML in your Contao modules. To communicate between the frontend and database, we will use the built-in MooTools framework, that is attached to every page template by default.
It is always good to show how things work on an example, so I will show you this on the CD Collection module, that we developed some time ago.
I assume that you know how does the AJAX work in theory, so I will omit describing it. Let’s get to work.
The Javascript
First of all, we need to create a javascript code that will do all the magic. As you know from previous tutorials, all stylesheets, images or javascript files are usually stored in the html folder of your module. Therefore go to /system/modules/cd_collection/html/ and create a file named ajax.js.
Open it and put the following code:
var doAjax = function(e){
e.stop(); // prevent the form from submitting
new Request({
url: window.location + '?isAjax=1',
method: 'post',
data: this,
onRequest: function(){
$('cd_collection').fade('out');
},
onSuccess: function(r){
// the 'r' is response from server
$('cd_collection').set('html', r).fade('in');
}
}).send();
}
addEvent('domready', function(){
$('form').addEvent('submit', doAjax);
});
Let’s take a closer look at it.
In the beginning, we stop the form submit process. Thus, no redirection is made. Next, we create a new Request object. Notice that we add &isAjax=1 to the URL. We do not modify the data to send, so it will pass values like in a normal form.
If the request is success, we simply put the response into content and display it.
Finally, we assign the doAjax method to the form. It will be launched once the form is submitted.
The PHP
Once we made that our ajax request will be recognized when there’s a _GET variable isAjax set to 1, we need to create a php code that will return proper data.
Open the ModuleCdCollection.php file and just before the compile() function ends, insert:
$GLOBALS['TL_JAVASCRIPT'][] = 'system/modules/cd_collection/html/ajax.js';
if ($this->Input->get('isAjax') == '1')
{
$intId = $this->Input->post('cat');
$objReturn = $this->Database->prepare("SELECT cd.*, cat.title AS catTitle, cat.description AS catDescription FROM tl_cds_category AS cat JOIN tl_cds AS cd ON (cd.pid = cat.id) WHERE cat.id=?")->execute($intId);
$strReturn = '<table border="0" cellpadding"4">';
while ($objReturn->next())
{
$strReturn .= sprintf(
'<tr>
<td><img src="%s" height="100" width="100" alt="%s" /></td>
<td>
<p><strong>%s</strong></p>
%s
</td>
</tr>',
$objReturn->image, $objReturn->title, $objReturn->title, $objReturn->artist, $objReturn->comment);
}
$strReturn .= '</table>';
$strReturn = sprintf('<h3>%s</h3>%s', $objReturn->catTitle, $objReturn->catDescription) . $strReturn;
print $strReturn;
exit; // IMPORTANT!
}
Now an explanation:
Line 1 – include the javascript file that we created a while ago. By putting its path to TL_JAVASCRIPT array, we make it attached to fe_ template.
Line 5 – fetch the value from the input (dropdown menu) which name is ‘cat’.
Line 7 – run a query that will fetch the category title and description, plus all the fields from tl_cds table.
Line 9 – create a string that will be returned. The HTML code of returned string should be same as in templates/mod_cdcollection.tpl file.
Line 13-21 – for each of the cds, create a new row in table and put the cd info there.
Line 25 – add title and description of the current category.
Line 27 – display the output, so that the javascript can “read” it.
Line 28 – prevent Contao from rendering the whole page.
Now it’s time to slightly modify the module template, so that the JS code can do the magic.
The HTML
Open up the templates/mod_cdcollection.tpl and apply the following changes:
<form action="" method="GET"> <!-- add ID: --> <form id="form" action="" method="POST"> <!-- wrap the cds list into div: --> <div id="cd_collection"> <h3><?php echo $this->catTitle; ?></h3> ... </div>
The modified file should look like this:
<span>Choose the category:</span>
<form id="form" action="" method="POST">
<select name="cat">
<?php foreach($this->categories as $category): ?>
<option value="<?php echo $category['id']; ?>"<?php if ($category['selected']): ?> selected="selected"<?php endif; ?>><?php echo $category['title']; ?></option>
<?php endforeach; ?>
</select>
<input type="submit" value="OK" />
</form>
<div id="cd_collection">
<h3><?php echo $this->catTitle; ?></h3>
<?php echo $this->catDescription; ?>
<table border="0" cellpadding="4">
<?php foreach ($this->cds as $cd): ?>
<tr>
<td><img src="<?php echo $cd['src']; ?>" height="100" width="100" alt="<?php echo $cd['alt']; ?>" /></td>
<td>
<p><strong><?php echo $cd['title']; ?></strong> (<?php echo $cd['artist']; ?>)</p>
<?php echo $cd['comment']; ?>
</td>
</tr>
<?php endforeach; ?>
</table>
</div>
Now go and test it!
To debug an ajax response, you can install an excellent Firefox tool called Firebug.
About Author
Lolke October 6th
Just getting started with contao and have basic knowledge of JS. I noticed that JS syntax has quite extensively evolved with in-place definitions of functions (ajax.js). Looks like this technique is quite powerful once you got used to it.
This post looks really cool. Think I can learn quite a bit from it. However, what I am missing is how it all fits together. Maybe a good idea to wrap it all up in a download?
Lolke October 6th
Ha! I see… I was supposed to have read the ‘Create a custom Contao Module’ series first…
Cyrus munyao February 22nd
Hello qzy,
I think this should this:
action=”GET”
be changed to:
action=”POST”
for the file to work
Kamil Kuzminski February 22nd
You are totally right, thanks
Cyrus munyao February 23rd
I’m glad you noticed this. You are my Contao development source of inspiration. Keep up and thanks for being my contao dad.
Cyrus munyao February 23rd
Hi Qzy.
I’m developing a contao fronted module using jquery framework. Do you have an idea how i should post the json data into database?
Kamil Kuzminski February 23rd
Thanks for positive feedback
Well, you need to parse this data, put into array and uset set() method http://pstbn.com/geimbwg
Andreas April 17th
So that your HTML is valid XHTML you have to write ‘GET’ and ‘POST’ in lowercase ‘get’ and ‘post’. And you have to put a DIV element (optional with class=”formbody”) as first element into your FORM elements, like Leo does in his templates.
Kamil Kuzminski April 17th
@Andreas
Thanks for pointing that out
madhamster June 12th
I think there’s gonna be a bug, if we’ll have two ajax powered modules on one page… May be add &module=cd_colletion to ajax request url, and then also check for match in: if ($this->Input->get(‘isAjax’) == ’1′ && $this->Input->get(‘module’) == ‘cd_collection’).
Kamil Kuzminski June 12th
@madhamster
Of course if you have several components use ajax then you have to split the results somehow. For example in of the projects I had three different ajax requests, and I simply used other var names than isAjax: e.g. updateCalendar, updateFields, getPrices etc.
Then you simply use the code presented in this post, but replace “isAjax” with other actions. There are many ways to have multiple ajaxes, choose the one which suits you best
Swathi June 27th
Hi ,
I have s:file upload tag in my jsp.and one sx:autocompleter tag.
if i change the element in sx:autocompleter the ajax to work.
But the s:file tag is preventing not to work ajax properly.
Can you give me some idea.Pls…..
Im trying this for past one week…..
Thanks in advance.
Kamil Kuzminski June 27th
@Swanthi
I have no idea about JSP, so I can’t help you. I think you should request a support somewhere else.
anon September 14th
hugs to you unknown polish guy, you saved me with this tutorial
Add Yours
YOU