Update multiple fields with one ajax request response
I searched for a possibility to update multiple fields with each ajax request made by a remoteTimer, but didn’t find any satisfying explanation on the web. To get that right, each field should get updated with the same response of a request.
So I had a look closer into the ajax helper and the prototype framework and came up with a little hack that suffice my needs and might be also helpful for others.
In the ajax helper (cake/libs/helpers/ajax.php) we first have to look into what happens when the options[update] parameter is set to an array with the different fields we want to update. That leads us to the ‘remoteFunction’ where following happens in that case:
$func = "new Ajax.Updater(document.createElement('div'),";
I have no clue what the creation of the div is really good for, but anyway we have to replace it with a JavaScript array holding the id’s of our fields:
$update = '['; foreach($options['update'] as $option) { $update .= "'" . $option . "',"; } $update .= ']'; $func = "new Ajax.Updater({$update},";
Now we must have a look into the prototype framework (app/webroot/js/prototype.js) and make sure the function Ajax.Updater can handle that array. The important function there is called updateContent:
Ajax.Updater = Class.create(); Object.extend(Object.extend(Ajax.Updater.prototype, Ajax.Request.prototype), { [...] updateContent: function() { [...] if (receiver = $(receiver)) { if (this.options.insertion) new this.options.insertion(receiver, response); else receiver.update(response); } [...] } });
Because the receiver is now our array, we must step through it and send a response to each of it:
Ajax.Updater = Class.create(); Object.extend(Object.extend(Ajax.Updater.prototype, Ajax.Request.prototype), { [...] updateContent: function() { [...] if (receiver.constructor.toString().indexOf("Array") != -1) { for(var i = 0; i < receiver.length; i++) { if(r = $(receiver[i])) { if (this.options.insertion) new this.options.insertion(r, response); else r.update(response); } } } else { if (receiver = $(receiver)) { if (this.options.insertion) new this.options.insertion(receiver, response); else receiver.update(response); } } [...] } });[/sourcecode] After checking if the receiver is actually an array, we step through it and send the response to every our fields. Finished! You can now use it like: [sourcecode language="php"] <?php echo $ajax->remoteTimer(array('url' => 'controller/action', 'update' => array('field1', 'field2', 'field3'), 'frequency' => '5')); ?>