有时候,我们在注册时,在页面的文本框中输入信息接着切换到下一个文本框时,原先的文本框就会自动的通过Ajax提交给服务器来进行实时的跟踪校验(例如:判断当前输入的用户名是否已经存在),这看起来很帅,同时也增强了用户友好性体验,我们称之为自动校验。那么在基于ROR的开发中,怎样实现这一功能呢?接下来就来具体的讨论如何用Rails来实现文本框信息的自动校验功能:
首先在实现这一功能时,先介绍一个辅助方法:observe_field(field_id, options={})
正如它的名字(“观察域”)一样,它一般被用于视图模块上监控输入域的值的变化,当被监控的值改变时实现Ajax的提交处理。它接收的参数有两个参数,一个是页面上的域的ID属性值,用于指定监听的域,另一个是Hash选项,具体可以查看它的API文档。
好上现在我们开始着手实现,先建立一个简单的erb模板,内容如下:
<html>
<head>
<title>自动测试文本的更新</title>
</head>
<body>
<%= "自动检验测试" %>
<% form_tag('javascript:void(0)') do %>
<%= text_field_tag :text_test %>
<% end %>
</body>
</html>
这里的javascript:void(0)阻止表单的提交,这里其实用不着,但在实际的项目中可能有用,这样做比传统的在action属性上加“#”号的方法更有效。
上面的代码只是在页面上形成一个普通的带有一个输入框的表单,如果要实现值的实时跟踪监控,则就必须使用上面介绍的observe_field()方法,现更改上述代码如下:
<html>
<head>
<title>自动测试文本的更新</title>
<%= javascript_include_tag :defaults %>
</head>
<body>
<%= "自动检验测试" %>
<% form_tag('javascript:void(0)') do %>
<%= text_field_tag :text_test %>
<%#下面是生成监视作用的代码,用于监视输入框text_test的值的变化%>
<%= observe_field :text_test, :update => 'user_result',
:url => {:action=> 'validate_text', :only_path=>false},
:with => "'text_test='+ encodeURIComponent(value)" %>
<div id="user_result"></div>
<% end %>
</body>
</html>
上面的代码说明了将跟踪text_test输入框的值,如果值改变了则Ajax提交给当前控制器的validate_text action处理。并将返回的结果更新在ID值为user_result的DIV的innerHTML属性中,with指的是提交时所带的参数,encodeURIComponent()方法是一个javascript方法用于格式化输入的值。由这所有的这些都是调用的Rails框架中的Javascript代码,故要调用javascript_include_tag来引入默认的javascript文件。
接着实现Action方法,它判断输入的值是否为空。如果不为空,则在user_result中显示用户输入的值:
#验证合法性
def validate_text
text_test = params[:text_test]
if text_test&&text_test.length!=0
render :inline => "<img src='/images/true.png' />测试#{ text_test }"
else
render :inline => "<img src='/images/false.png' />"
end
end
上面的基本上已经实现了自动检验功能,但很不友好,即当用户访问量很大时,客户可能会不耐烦,这时我们必须给出相应的加载信息,用于安抚用户,说明我们的程序正在努力的加载。这就必须用到observe_field()方法的回调功能,更改视图模板如下:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>自动测试文本的更新</title>
<%= javascript_include_tag :defaults %>
</head>
<body>
<%= "自动检验测试" %>
<% form_tag('javascript:void(0)') do %>
<%= text_field_tag :text_test %>
<%#下面是生成监视作用的代码,用于监视输入框text_test的值的变化%>
<%= observe_field :text_test, :update => 'user_result',
:before=>"Element.show('spinner'); Element.hide('user_result')",
:after=>"Element.hide('spinner'); Element.show('user_result')",
:url => {:action=> 'validate_text', :only_path=>false},
:with => "'text_test='+ encodeURIComponent(value)" %>
<div id="spinner" style="display: none"><img src="/images/loading.gif" /></div>
<div id="user_result"></div>
<% end %>
</body>
</html>
这里由于调用了javascript的getElementById() DOM方法,所以必须加上HTML的头信息。上面的代码说明当前用户提交时显示一张动态加载图片,完成后将其隐藏。其中的:before选项的代码在Ajax提交前执行,而:after选项的代码在Ajax提交完成后执行。Element.show(field_id)和Element.hide(field_id)为显示隐藏元素.其实常用的observe_field()选项方法还有:frequency用于指定监控频率,更多的选项可以参考它的API。
最终实再效果如下:
初始化页面
输入文本提交
Ajax处理完成
最后删除文本