Ajax驱动的表单
Web表单一般要调用另一个动作, 但这会导致整个页面被刷新. 对表单来说,类似于 link_to_function() 的功能可以让表单的提交后, 仅用服务器的响应去更新页面中的一个元素, form_remote_tag()辅助函数就是完成这个任务, 表11-11展示了它的语法:
表11-11 使用form_remote_tag() 辅助函数的Ajax 表单
[php]
<div id="item_list"></div>
<?php echo form_remote_tag(array(
'update' => 'item_list',
'url' => 'item/add',
)) ?>
<label for="item">Item:</label>
<?php echo input_tag('item') ?>
<?php echo submit_tag('Add') ?>
</form>
例子中, 类似form_tag() 辅助函数, form_remote_tag()打开一个
. 提交这个表单会在后台向item/add动作发出一个POST请求, 请求的参数就是item域的内容. 响应会替换item_list元素的内容(如图11-2所示). 最后用正规的
标记关闭Ajax 表单.
图11-2 触发一个带有表单的远程更新.
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 XMLHttpRequest (see an implementation at
http://www.air4web.com/files/upload/).注意 由于XMLHttpRequest对象的限制, Ajax表单不可以分为多个部分.这意味着你不能通过Ajax表单上传文件. 不过可以用其他方法解决这个问题—比如, 用隐式的iframe代替XMLHttpRequest(参看
http://www.air4web.com/files/upload/给出的一个实现)
如果你想让一个表但同时工作在页模式和Ajax模式, 最好的方法是定义一个正规的表单, 然后除了提供通用的提交按钮, 再增加一个按钮(<input type=”button”/>)用于以Ajax方式提交表单. symfony将这个按钮称为submit_to_remote().这有助于你建立一个与以前的方法兼容的Ajax交互表单.
表11-12 具有正常提交和Ajax提交的表单
[php]
<div id="item_list"></div>
<?php echo form_tag([email=]'@item_add_regular'[/email]) ?>
<label for="item">Item:</label>
<?php echo input_tag('item') ?>
<?php if_javascript(); ?>
<?php echo submit_to_remote('ajax_submit', 'Add in Ajax', array(
'update' => 'item_list',
'url' => [email=]'@item_add'[/email],
)) ?>
<?php end_if_javascript(); ?>
<noscript>
<?php echo submit_tag('Add') ?>
</noscript>
</form>
混合了正常提交和Ajax提交标记的例子还有用于编辑文章的表单. 它可以提供一个用Ajax提交实现的预览按钮和一个用普通提交实现的发布按钮.
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.注意 当用户按下回车键时, 表单会用定义在主要的
标记中的动作去提交,在 本例中, 就是正常提交动作. 现代表单不仅仅在提交时才作出反应, 在用户改变某个域的值时也会有反应.在symfony中, 你可以用observe_field()辅助函数来实现. 表11-13给出了一个使用这个辅助函数的例子, 在item域中每输入一个字符, 都会触发一个Ajax调用去刷新页面中的item_suggestion. 表11-13 当值变化时, 由observe_field()调用一个远程函数. [php] Item:
'item_suggestion', 'url' => [email=]'@item_being_typed'[/email], )) ?>
每当用户改变了域item(成为”发现域”)的值时, 即使没有提交表单, 也会调用@item_being_typed规则中的模块/动作. 这个动作将从value请求参数中获得当前的item值. 如果你想传递非发现域的内容, 你可以用javascript表达式的with参数来指明. 例如, 如果你想让动作得到param参数, 可以将observe_field()写成如下形式(表11-14):
表11-14 用with 选项将你自己的参数传递给远程动作
[php]
<?php echo observe_field('item', array(
'update' => 'item_suggestion',
'url' => [email=]'@item_being_typed'[/email],
'with' => "'param=' + value",
)) ?>
注意, 这个辅助函数并不输出一个HTML元素, 而是输出作为一个参数的元素的行为.在本章中你会看到更多指定行为的javascript 辅助函数的例子.
如果你想发现一个表单中的所有域, 你可以使用observe_form() 辅助函数, 每当表单中的任意一个域发生变化时, 它都会调用一个远程动作.