![]() |
|
Snippets |
|
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.
Comments on this snippet
Nice. Glad you finally posted your idea as a snippet.
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); }
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