本文翻译出处 http://tapestry.apache.org/tapestry5/tapestry-core/guide/validation.html
本人翻译目的是用来学习Tapestry5的,共享出来希望大家批评指正。计划持续翻译。
chinajavawolf
表单输入和验证
对于任何应用表单输入都是必不可少的;这是更有效的从用户处收集有用信息的方法。不管它是一个搜索表单、一个登录窗口或是一个多页的注册向导,用户使用表单真正向应用表达自己。
Tapestry
在创建表单和验证输入方面表现杰出。输入验证是声明式的,这意味着你只是告诉
Tapestry
在给出的那个表单域上应用什么验证,然后他就会在服务器端和客户端负责验证。
最后,Tapestry不仅能够将错误的信息表现给用户,还能对表单域和表单域地标签进行装饰,标记它们包含错误(主要利用CSS效果)。
表单组件
当呈现的时候,表单组件发布一个
”prepare”
通知,以使表单容器设置将要在表单中引用的表单域或属性。这是一个创建用来呈现的临时实体对象或用来加载来自于数据库的可编辑的实体的好时机。
当用户在客户端提交表单时,服务器端会执行一系列的步骤。
首先,当表单被呈现时表单会发出一个
"prepare"通知。
接下来,所有的表单域被激活从引用的请求处获值,验证它们并(如果有效)保存变化。
对Tapestry 4的用户:Tapestry 5不使用Tapestry 4中脆弱的
"form rewind"方法,而是用在呈现时产生一个存放是否需要处理表单提交信息的隐藏域来代替。
表单域流程处理完后,表单发出一个
"validate"事件,
这是执行跨表单验证的不能明白地被描述的一个机会。
接下来,表单确定是否存在任何验证错误。如果存在,那么提交一个被评估过的失败并发出一个
"failure"事件。如果没有验证错误,那么将发出一个
"success"事件。
最后,表单发出一个
"submit"
事件(逻辑上它不考虑成功还是失败
)。
跟踪验证错误
一个与表单关联的就是验证跟踪器
ValidationTracker跟踪用户所有对每个表单域提供的书如何验证错误。跟踪器能够通过表单的跟踪器参数提供给表单,但这不是必需的。
表单包括
isValid()
和
getHasErrors()
方法,他们被用来了解表单验证的跟踪器中是否包含错误。
在你自己的逻辑中,你可以去纪录你自己的错误。表单包括两个不同的
recordError()
方法版本。一个是指定一个表单域(一个被所有表单元素组件实现的接口),另外一个是全局"global"错误,与具体的表单域无关。
请求间存储数据
由于其他的动作请求,表单提交的结果会发送给客户端一个重定向去重新呈现页面。验证跟踪器必须在请求间被持久化地存储,否则所有的验证信息将被丢失(表单提供持久化式的默认验证跟踪器)。
同样,被组件更新的单独的表单域也应该被持久化。
例如,一个用来收集用户名和密码登陆页,如下:
- public class Login
- {
- @Persist
- private String _userName;
-
- private String _password;
-
- @Inject
- private UserAuthenticator _authenticator;
-
- @Component(id = "password")
- private PasswordField _passwordField;
-
- @Component
- private Form _form;
-
- String onSuccess()
- {
- if (!_authenticator.isValid(_userName, _password))
- {
- _form.recordError(_passwordField, "Invalid user name or password.");
- return null;
- }
-
- return "PostLogin";
- }
-
- public String getPassword()
- {
- return _password;
- }
-
- public void setPassword(String password)
- {
- _password = password;
- }
-
- public String getUserName()
- {
- return _userName;
- }
-
- public void setUserName(String userName)
- {
- _userName = userName;
- }
- }
因为Form表单提交事实上是两个请求(提交自己,然后重新呈现页面),他需要在两个请求间产生一个值持续存储在_userName属性中。同样
_password属性
也应该被这样做,除非
PasswordField
组件从不呈现值。
注意
onSuccess()
不是公有的;事件处理器方法可以有任何可见度,甚至是私有的。包私有(就是没有修饰符)是典型应用,这样它允许组件可被相同包下的测试用例类测试。
如果先前没有验证错误,表单就只发出一个
"success"
事件。这意味着不用写
if (_form.getHasErrors()) return;
在方法的第一行。
最后,注意业务逻辑如何与表单验证相适合。
UserAuthenticator
服务负责
userName
和
password
的有效性。当它返回false时,我们用Form组件来记录一个错误。我们提供
PasswordField
实例作为第一个参数;这保证了
password
表单域和他的标签在表单重新呈现时被装饰以呈现错误给用户。
配置表单域和标签
页面模板包含最少的
Tapestry
内容
- <html xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd">
- <head>
- <title>Logintitle>
- head>
- <body>
- <h1>Please Loginh1>
-
- <t:form>
-
- <t:errors/>
-
- <t:label for="userName"/>:
- <input t:type="TextField" t:id="userName" t:validate="required,minlength=3" size="30"/>
- <br/>
- <t:label for="password"/>:
- <input t:type="PasswordField" t:id="password" t:validate="required,minlength=3" size="30"/>
- <br/>
- <input type="submit" value="Login"/>
- t:form>
- body>
- html>
Tapestry表单组件负责为表单提交创建必需的URL(这是Tapestry的职责,不是你的)。
Errors
组建必须被放在表单里,他通过一个单独的列表输出表单中所有表单域的错误。他使用一些简单的样式使结果更突出。
每个表单组件,例如
TextField,
和
Label
组件是一对的。标签将呈现出一个
元素和表单域关联。这对于应用是很有用的,尤其是有视觉障碍的用户。它意味着你可以能过点击标签文本将光标移到相应的表单域。
Label
的
for
参数就是组件的
id.
对于
TextFile,
我们提供一个组件
id,userName.
我们能够指定
value
参数,默认情况下这个参数是匹配TextField的id,TextField的id又对应于容器的一个属性,这个容器就是Loing页,如果这个属性存在。
根据经验,你应该给你的表单域指定一个
id(这个id将被用来产生呈现标签的name与id属性
). 被允许省略value参数以帮助保持模板不变得更混乱。
验证参数确认表单域应该发生什么验证。这是一个验证器的名字列表。验证器被配置在Tapestry内,并且有效的验证器列表是可扩展的。。"required"是一个内置验证器的名字,用来保证提交的值不为空串,此外,"minlen"用来保证值有指定的最小长度。
验证参数使用
t:
前缀放置在
Tapestry
的命名空间里。这不是必须严格要求的,只是模板可以拥有良好的格式。然而,在Tapestry命名空间放置Tapestry特定值保证了模板自身的有效性。
错误和装饰
注意:这部分并没有更新到涉及客户端输入验证的介绍。
当你第一次激活登陆页时,表单域和表单都将正常呈现,等待输入:
注意标签组件是如何显示表单域的文本名字的。我们没做任何显式地配置,组件的ids
("userName" and "password")已经转成"User Name" 和 "Password",这发生了什么?。
如果你这样提交表单,表单域将违背
"required"
约束,那么页面将重新显示错误呈现给用户。
这里发生了两个微妙的事情。首先,Tapestry跟踪所有表单域的所有错误信息。Errors组件显示在表单的最上面。此外,默认的验证修饰器给标签和表单域加上了t-error CSS类样式。Tapestry提供了默认的 CSS样式与
"t-error"
类结合使得它们变红。
接下来,我们填充上用户名,但不用提供足够的字符串给密码。
用户名是正确的,但是有一个错误在密码上。
PasswordField
组件默认是经常显示一个空值,另外我们看到只密码部分在那里。
如果有足够的字符串被提交,我们会看到Login页面是如何将逻辑错误加入到表单域的错误里:
这可真是天衣无缝,对于内置的验证器和基于应用逻辑产生的错误在外观、感觉和行为上都像是一样的。