remote_function() helper does exactly that, as demonstrated in Listing 11-8.
Listing 11-8 - Using the
url parameter can contain either an internal URI (
module/action?key1=value1&...) or a routing rule name, just as in a regular
When called, this script will update the element of id myzone with the response or the request of the
mymodule/myaction action. This kind of interaction is called Ajax, and it's the heart of highly interactive web applications. Here is how Wikipedia (http://en.wikipedia.org/wiki/AJAX) describes it:
Ajax makes web pages feel more responsive by exchanging small amounts of data with the server behind the scenes, so that the entire web page does not have to be reloaded each time the user makes a change. This is meant to increase the web page's interactivity, speed, and usability.
Ajax relies on
Caution The Ajax helpers won't work if the URL of the remote action doesn't belong to the same domain as the current page. This restriction exists for security reasons, and relies on browsers limitations that cannot be bypassed.
11.3.1. Ajax Link
Ajax links form a large share of the Ajax interactions available in Web 2.0 applications. The
link_to_remote() helper outputs a link that calls, not surprisingly, a remote function. The syntax is very similar to that of
link_to() (except that the second parameter is the associative array of Ajax options), as shown in Listing 11-9.
Listing 11-9 - Ajax Link with the
<div id="feedback"></div> echo link_to_remote('Delete this post', array( 'update' => 'feedback', 'url' => 'post/delete?id='.$post->getId(), ))
In this example, clicking the
'Delete this post' link will issue a call to the
post/delete action in the background. The response returned by the server will appear in the element of
feedback. This process is illustrated in Figure 11-1.
You can use an image instead of a string to bear the link, use a rule name instead of an internal module/action URL, and add options to the
<a> tag in a third argument, as shown in Listing 11-10.
Listing 11-10 - Options of the
<div id="emails"></div> echo link_to_remote(image_tag('refresh'), array( 'update' => 'emails', 'url' => '@list_emails', ), array( 'class' => 'ajax_link', ))
11.3.2. Ajax-Driven Forms
Web forms typically call another action, but this causes the whole page to be refreshed. The correspondence of the
link_to_function() for a form would be that the form submission only updates an element in the page with the server response. This is what the
form_remote_tag() helper does, and its syntax is demonstrated in Listing 11-11.
Listing 11-11 - Ajax Form with the
<div id="item_list"></div> echo form_remote_tag(array( 'update' => 'item_list', 'url' => 'item/add', )) <label for="item">Item:</label> echo input_tag('item') echo submit_tag('Add') </form>
form_remote_tag() opens a
<form>, just like the regular
form_tag() helper. Submitting this form will issue a POST request to the
item/add action in the background, with the
item field as a request parameter. The response will replace the contents of the
item_list element, as illustrated in Figure 11-2. Close an Ajax form with a regular
</form> closing tag.
Caution Ajax forms can't be multipart. This is a limitation of the
XMLHttpRequest object. This means you can't handle file uploads via an Ajax form. There are workarounds though--for instance, using a hidden
iframe instead of an
If you want to allow a form to work in both page mode and Ajax mode, the best solution is to define it like a regular form, but to provide, in addition to the normal submit button, a second button (
<input type="button" />) to submit the form in Ajax. Symfony calls this button
submit_to_remote(). This will help you build Ajax interactions that degrade gracefully. See an example in Listing 11-12.
Listing 11-12 - A Form with Regular and Ajax Submission
Another example of combined use of remote and regular submit tags is a form that edits an article. It can offer a preview button in Ajax and a publish button that does a regular submission.
Note When the user presses the Enter key, the form is submitted using the action defined in the main
<form> tag — in this example, a regular action.
Modern forms can also react not only when submitted, but also when the value of a field is being updated by a user. In symfony, you use the
observe_field() helper for that. Listing 11-13 shows an example of using this helper to build a suggestion feature: Each character typed in an
item field triggers an Ajax call refreshing the
item_suggestion element in the page.
Listing 11-13 - Calling a Remote Function When a Field Value Changes with
echo form_tag('@item_add_regular') <label for="item">Item:</label> echo input_tag('item') <div id="item_suggestion"></div> echo observe_field('item', array( 'update' => 'item_suggestion', 'url' => '@item_being_typed', )) echo submit_tag('Add') </form>
The module/action written in the
@item_being_typed rule will be called each time the user changes the value of the observed field (
item), even without submitting the form. The action will be able to get the current
item value from the
with parameter. For instance, if you want the action to get a
param parameter, write the
observe_field() helper as shown in Listing 11-14.
Listing 11-14 - Passing Your Own Parameters to the Remote Action with the
echo observe_field('item', array( 'update' => 'item_suggestion', 'url' => '@item_being_typed', 'with' => "'param=' + value", ))
If you want to observe all the fields of a form, you should use the
observe_form() helper, which calls a remote function each time one of the form fields is modified.
11.3.3. Periodically Calling Remote Functions
Last but not least, the
periodically_call_remote() helper is an Ajax interaction triggered every few seconds. It is not attached to an HTML control, but runs transparently in the background, as a behavior of the whole page. This can be of great use to track the position of the mouse, autosave the content of a large text area, and so on. Listing 11-15 shows an example of using this helper.
Listing 11-15 - Periodically Calling a Remote Function with
<div id="notification"></div> echo periodically_call_remote(array( 'frequency' => 60, 'update' => 'notification', 'url' => '@watch', 'with' => "'param=' + \$F('mycontent')", ))
If you don't specify the number of seconds (
frequency) to wait between two calls to the remote function, the default value of 10 seconds is used. Note that the