我去创建一个登陆的表单并且设置一个超链接到注册页面:
<html xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd">
<head>
<title>Celebrity Collector</title>
</head>
<body>
<h1>Celebrity Collector</h1>
<p> Log in here: </p>
<t:form t:id="loginForm">
<table>
<tr>
<td>
<t:label t:for="userName">
Label for the first text box</t:label>:
</td>
<td>
<input type="text" t:id="userName"
t:type="TextField" t:value="userName"/>
</td>
</tr>
<tr>
<td>
<t:label t:for="password">
The second label</t:label>:
</td>
<td>
<input type="text" t:id="password"
t:type="PasswordField" t:value="password"/>
</td>
</tr>
<tr>
<td colspan="2" align="center">
<input type="submit" value="Log In"/>
</td>
</tr>
</table>
</t:form>
<p>
<a href="#" t:type="PageLink" t:page="Registration">
Or register</a>
</p>
</body>
</html>
看看上面的代码,可以看到有一个
Form
的组件,一个
Tapestry
的命名空间。明确的:在一个
Form
中有四个
Tapestry
组件。有两个是
Label
这是很容易看出来的。看到有两个不同的:
TextField & PasswordField---
隐藏在
HTML
控件
<input type=”text”>
中。为什么要混合使用这两种方法去定义
Tapestry
组件?
如果我想通过浏览器预览一下页面,这些隐藏在其中的组件就能被
HTML
控件自己渲染出来。然而,有些组件对于页面来说是无形的,比如
Form
,还有一些是被渲染成纯文本的形式,比如
Label
,这些可以简单的明确的定义。
看看下面这对组件:
<td>
<t:label t:for="userName">
Label for the first text box</t:label>:
</td>
<td>
<input type="text" t:id="userName" t:type="TextField"
t:value="userName"/>
</td>
第二个,文本框,对于我们来说早就熟悉了,但是在这里它有一个
”t:id="userName"
的属性。第一个组件是一个新的,我们可以看到,这是一个标签类型,并且他的
t:for
属性是和
TextField
的
t:id
对应的,所以他是这个文本框的标签。
注意
<t:label>
标签周围的字,作者说他是故意写这么长的,是为了变魔术给大家看,在页面加载完以后,这些字就没有了,取而代之的是一个新的,在这里是
USERNAME
。
我们配合作者为一下,好神奇,为什么呢?原来这个
LABEL
组件是指向其他组件的一个
label
属性,并且能把他正确的显示出来。(说实话,我不信,因为我总是显示中间的那些字)。
来看看这个:
<input type="text" t:type="TextField" t:id="userName" t:label="User Name" t:value="userName"/>
看,多出个
t:label
属性,明白了吧。但是如果没有
t:label
标签,
Tapestry
就会找到
t
:
id
,并且把字符串分离,首字母大写的显示。
PasswordField
和
FiledText
差不多
然后是个
PageLink
这个暂时也没有什么好说的,在前面已经用到过了。
完成了这个页面,接下来该在类当中加写功能,去处理页面的请求了。我们需要两个属性
username
和
password
,还要一个方法去处理提交的表单:
1、
用之前创建的
Security
类去验证输入的信息
2、
如果验证成功,则把
user
作为一个
ASO
保存起来,并且跳转到
showall
压面
3、如果验证失败,没有user保存,并且跳到注册页面。
package com.packtpub.celebrities.pages;
import com.packtpub.celebrities.util.Security;
import com.packtpub.celebrities.model.User;
import org.apache.tapestry.annotations.ApplicationState;
import org.apache.tapestry.annotations.OnEvent;
public class Start
{
private String userName;
private String password;
@ApplicationState
private User user;
Object onSubmitFromLoginForm()
{
Class nextPage = null;
User authenticatedUser = null;
authenticatedUser =
Security.authenticate(userName, password);
if (authenticatedUser != null)
{
user = authenticatedUser;
nextPage = ShowAll.class;
}
else
{
nextPage = Registration.class;
}
return nextPage;
}
public String getUserName()
{
return userName;
}
public void setUserName(String userName)
{
this.userName = userName;
}
public String getPassword()
{
return password;
}
public void setPassword(String password)
{
this.password = password;
}
}
在上面那个页面,
OR
register
连接实现了一个
PAGELINK
组件,但是并没有什么新的东西,但是如果你去看
Tapestry
关于
pagelink
的文档,就会发现它还有一个
context
属性,这个属性不是必须的,但是确实非常有用的。