All the Ajax helpers described in the previous sections can take other parameters, in addition to the update
and url
parameters. The associative array of Ajax parameters can alter and tweak the behavior of the remote calls and the processing of their response.
11.4.1. Updating Distinct Elements According to the Response Status
If the remote action fails, the remote helpers can choose to update another element than the one updated by a successful response. To that purpose, just split the value of the update
parameter into an associative array, and set different values for the element to update in cases of success
and failure
. This is of great use if, for instance, there are many Ajax interactions in a page and one error feedback zone. Listing 11-16 demonstrates handling a conditional update.
Listing 11-16 - Handling a Conditional Update
<div id="error"></div>
<div id="feedback"></div>
<p>Hello, World!</p>
<?php echo link_to_remote('Delete this post', array(
'update' => array('success' => 'feedback', 'failure' => 'error'),
'url' => 'post/delete?id='.$post->getId(),
)) ?>
Tip Only HTTP error codes (500, 404, and all codes not in the 2XX range) will trigger the failure update, not the actions returning sfView::ERROR
. So if you want to make an action return an Ajax failure, it must call $this->getResponse()->setStatusCode(404)
or similar.
11.4.2. Updating an Element According to Position
Just as with the update_element_function()
helper, you can specify the element to update as relative to a specific element by adding a position
parameter. Listing 11-17 shows an example.
Listing 11-17 - Using the Position Parameter to Change the Response Location
<div id="feedback"></div>
<p>Hello, World!</p>
<?php echo link_to_remote('Delete this post', array(
'update' => 'feedback',
'url' => 'post/delete?id='.$post->getId(),
'position' => 'after',
)) ?>
This will insert the response of the Ajax call after the feedback
element; that is, between the <div>
and the <p>
. With this method, you can do several Ajax calls and see the responses accumulate after the update
element.
The position
parameter can take the following values:
before
: Before the elementafter
: After the elementtop
: At the top of the content of the elementbottom
: At the bottom of the content of the element
11.4.3. Updating an Element According to a Condition
A remote call can take an additional parameter to allow confirmation by the user before actually submitting the XMLHttpRequest
, as shown in Listing 11-18.
Listing 11-18 - Using the Confirm Parameter to Ask for a Confirmation Before Calling the Remote Function
<div id="feedback"></div>
<?php echo link_to_remote('Delete this post', array(
'update' => 'feedback',
'url' => 'post/delete?id='.$post->getId(),
'confirm' => 'Are you sure?',
)) ?>
A JavaScript dialog box showing "Are you sure?" will pop up when the user clicks the link, and the post/delete
action will be called only if the user confirms his choice by clicking OK.
The remote call can also be conditioned by a test performed on the browser side (in JavaScript), if you provide a condition
parameter, as shown in Listing 11-19.
Listing 11-19 - Conditionally Calling the Remote Function According to a Test on the Client Side
<div id="feedback"></div>
<?php echo link_to_remote('Delete this post', array(
'update' => 'feedback',
'url' => 'post/delete?id='.$post->getId(),
'condition' => "$('elementID') == true",
)) ?>
11.4.4. Determining the Ajax Request Method
By default, Ajax requests are made with the POST method. If you want to make an Ajax call that doesn't modify data, or if you want to display a form that has built-in validation as the result of an Ajax call, you might need to change the Ajax request method to GET. The method
option alters the Ajax request method, as shown in Listing 11-20.
Listing 11-20 - Changing the Ajax Request Method
<div id="feedback"></div>
<?php echo link_to_remote('Delete this post', array(
'update' => 'feedback',
'url' => 'post/delete?id='.$post->getId(),
'method' => 'get',
)) ?>
11.4.5. Authorizing Script Execution
If the response code of the Ajax call (the code sent by the server, inserted in the update
element) contains JavaScript, you might be surprised to see that these scripts are not executed by default. This is to reduce remote attack risks and to allow script execution only when the developer knows for sure what code is in the response.
That's why you need to declare explicitly the ability to execute scripts in remote responses, with the script
option. Listing 11-21 gives an example of an Ajax call declaring that JavaScript from the remote response can be executed.
Listing 11-21 - Authorizing Script Execution in the Ajax Response
<div id="feedback"></div>
<?php
// If the response of the post/delete action contains JavaScript,
// allow it to be executed by the browser
echo link_to_remote('Delete this post', array(
'update' => 'feedback',
'url' => 'post/delete?id='.$post->getId(),
'script' => true,
)) ?>
If the remote template contains Ajax helpers (such as remote_function()
), be aware that these PHP functions generate JavaScript code, and they won't execute unless you add the 'script' => true
option.
Note Even if you enable script execution for the remote response, you won't actually see the scripts in the remote code, if you use a tool to check the generated code. The scripts will execute but will not appear in the code. Although peculiar, this behavior is perfectly normal.
11.4.6. Creating Callbacks
One important drawback of Ajax interactions is that they are invisible to the user until the zone to update is actually updated. This means that in cases of a slow network or server failure, users may believe that their action was taken into account, when it actually was not processed. This is why it is important to notify the user of the events of an Ajax interaction.
By default, each remote request is an asynchronous process during which various JavaScript callbacks can be triggered (for progress indicators and the like). All callbacks have access to the request
object, which holds the underlying XMLHttpRequest
. The callbacks correspond to the events of any Ajax interaction:
before
: Before request is initiatedafter
: Immediately after request is initiated and before loadingloading
: When the remote response is being loaded by the browserloaded
: When the browser has finished loading the remote responseinteractive
: When the user can interact with the remote response, even though it has not finished loadingsuccess
: When theXMLHttpRequest
is completed, and the HTTP status code is in the 2XX rangefailure
: When theXMLHttpRequest
is completed, and the HTTP status code is not in the 2XX range404
: When the request returns a 404 statuscomplete
: When theXMLHttpRequest
is complete (fires aftersuccess
orfailure
, if they are present)
For instance, it is very common to show a loading indicator when a remote call is initiated, and to hide it once the response is received. To achieve that, simply add loading
and complete
parameters to the Ajax call, as shown in Listing 11-22.
Listing 11-22 - Using Ajax Callbacks to Show and Hide an Activity Indicator
<div id="feedback"></div>
<div id="indicator">Loading...</div>
<?php echo link_to_remote('Delete this post', array(
'update' => 'feedback',
'url' => 'post/delete?id='.$post->getId(),
'loading' => "Element.show('indicator')",
'complete' => "Element.hide('indicator')",
)) ?>
The show and hide methods, as well as the JavaScript Element object, are other useful additions of Prototype.