Ajax in Contao | qzminski Blog

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

Kamil Kuzminski

Hi! I'm a webdeveloper from Olsztyn, Poland. I'm the manager of Contao (fka TYPOlight) polish support website and community. I work mainly as a freelancer for private clients or various agencies.





Comments

  1. Lolke October 6th

    Comment Arrow

    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?


  2. Lolke October 6th

    Comment Arrow

    Ha! I see… I was supposed to have read the ‘Create a custom Contao Module’ series first…


  3. Cyrus munyao February 22nd

    Comment Arrow

    Hello qzy,
    I think this should this:
    action=”GET”

    be changed to:
    action=”POST”
    for the file to work


  4. Kamil Kuzminski February 22nd

    Comment Arrow

    You are totally right, thanks :)


  5. Cyrus munyao February 23rd

    Comment Arrow

    I’m glad you noticed this. You are my Contao development source of inspiration. Keep up and thanks for being my contao dad.


  6. Cyrus munyao February 23rd

    Comment Arrow

    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?


  7. Kamil Kuzminski February 23rd

    Comment Arrow

    Thanks for positive feedback :)
    Well, you need to parse this data, put into array and uset set() method http://pstbn.com/geimbwg


  8. Andreas April 17th

    Comment Arrow

    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.


  9. Kamil Kuzminski April 17th

    Comment Arrow

    @Andreas
    Thanks for pointing that out :)


  10. madhamster June 12th

    Comment Arrow

    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’).


  11. Kamil Kuzminski June 12th

    Comment Arrow

    @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 :)


  12. Swathi June 27th

    Comment Arrow

    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.


  13. Kamil Kuzminski June 27th

    Comment Arrow

    @Swanthi
    I have no idea about JSP, so I can’t help you. I think you should request a support somewhere else.


  14. anon September 14th

    Comment Arrow

    hugs to you unknown polish guy, you saved me with this tutorial


Add Yours

  • Author Avatar

    YOU


Comment Arrow