Snippets

Create an account or login to be able to add, comment and rate snippets.

Navigation

One link, multiple ajax div updates, only one remote call

The problem seems to arise quite frequently: a page contains one Ajax link, but the remote function must update several divs on the page. Consider, for instance, the following template:

<h1>First zone to update</h1>
<div id="first_zone">
  Hello there
</div>
 
<h1>Second zone to update</h1>
<div id="second_zone">
  <p>How do you do, <strong>mate</strong>?
</div>
 
<h1>Ajax link</h1>
<?php echo use_helper('Javascript') ?>
<?php echo link_to_remote('click me', array(
  'url'    => 'test/ajax',
  'update' => 'result',
  'script' => true,
)) ?>
<div id="result">
</div>

What would the test/ajax action look like to update both the first_zone and the second_zone?

For the code of the action itself (executeAjax()), we'll ignore it since it really depends on what logic you put in your Ajax interaction. For this example, it will be empty.

The code of the template (ajaxSuccess.php) can be as follows:

<?php echo use_helper('Javascript') ?>
 
<?php slot('first_update') ?>
  So you like clicking, uh?
<?php end_slot() ?>
 
<?php slot('second_update') ?>
  <p>I'd like to test quotes (like "). </p>
  <p>And <strong>tags</strong>, too.</p>
<?php end_slot() ?>
 
<?php echo javascript_tag(
 
  update_element_function('first_zone', array(
    'content' => get_slot('first_update'),
  ))
  .
  update_element_function('second_zone', array(
    'content' => get_slot('second_update'),
  )) 
 
) ?>
 

Once rendered, the HTML code sent to the user will look like this:

<script type="text/javascript">
//<![CDATA[
$('first_zone').innerHTML = '  So you like clicking, uh?\n';
$('second_zone').innerHTML = '  <p>I\'d like to test quotes (like \"). </p>\n  <p>And <strong>tags</strong>, too.</p>\n';
//]]>
</script>

And this will do exactly what we wanted: update both zones with different content, in a single remote call. The interest of using the slot helpers is that you don't need to worry about escaping the content passed to the JavaScript function, and it looks really nice in your favorite syntax-highlighting text editor.

If you happen to do this a lot, maybe you will want to package the multiple updater into a helper. That's quite easy:

function update_elements_function($updates)
{
  $res = "";
  foreach($updates as $zoneName => $slotName)
  {
    $res .= update_element_function($zoneName, array('content' => get_slot($slotName)));
  }
  return javascript_tag($res);
}

Then you could replace the call to the javascript_tag() in the ajaxSuccess.php template by a simpler:

<?php echo update_elements_function(array(
  'first_zone'  => 'first_update',
  'second_zone' => 'second_update',
)) ?>

Performancewise, if the Ajax response is small (below 512 Bytes), you'd better use the JSON approach.

by Francois Zaninotto on 2006-11-22, tagged ajax  helper  multiple 

Comments on this snippet

gravatar icon
#1 Stephen Riesenberg on 2006-11-25 at 06:55

Nice. Glad you finally posted your idea as a snippet.

gravatar icon
#2 Navid Nikpour on 2006-12-10 at 09:23

Hello Francois, your idea is nice indeed, but wouldn't it be better for the helper function to map slots to zones so that you can update various zones with the response of specific slot ? or do i just reinvent some already featured "wheel" ???

function update_elements_reverse_function($updates) { $res = ""; foreach($updates as $slotName => $zoneName) { if(is_array($zoneName)) foreach($zoneName as $zone) { $res.= update_element_function($zone, array('content' => get_slot($slotName))); else $res.= update_element_function($zoneName, array('content' => get_slot($slotName))); } return javascript_tag($res); }

gravatar icon
#3 Navid Nikpour on 2006-12-10 at 09:26

Sorry for that messy comment, i just pasted my code in which mapped slots => zones and concatenated the update_element_function to the zone-array elements if the zonenames turned out to be bundled in an array

You need to create an account or log in to post a comment or rate this snippet.