新聞中心
表單輸入與驗(yàn)證
表單輸入是任何應(yīng)用的生命之血;這是一種從用戶收集有用信息的最有效的方式。不管它是一個(gè)搜索表單、一個(gè)登錄還是一個(gè)多頁的注冊(cè)向?qū)?,用戶借助表單在?yīng)用中真正地表達(dá)他們。
Tapestry 5輸入驗(yàn)證在創(chuàng)建和驗(yàn)證輸入有很好的表現(xiàn)。輸入驗(yàn)證是聲明式的,意味首我們簡(jiǎn)單地告訴Tapestry一個(gè)表單域應(yīng)用哪種驗(yàn)證,然后Tapestry會(huì)在服務(wù)器端(已實(shí)現(xiàn))與客戶端維護(hù)這種驗(yàn)證。
最后,Tapestry不僅能夠?qū)㈠e(cuò)誤的信息表現(xiàn)給用戶,而且還能對(duì)表單域及其標(biāo)注(labels)進(jìn)行裝飾,標(biāo)記它們包含錯(cuò)誤(主要利用CSS效果)。
表單組件
Tapestry的表單支持的核心即是表單組件,表單組件封裝著其他所有表單域組件,如TextField、TextArea、Checkbox等等。
表單組件產(chǎn)生許多組件事件,我們可以給其提供事件處理方法。
呈現(xiàn)時(shí),表單組件發(fā)出一個(gè)“prepare”通知,以使表單容器創(chuàng)建將要在表單中引用的表單域或?qū)傩?。如,這是一個(gè)創(chuàng)建被呈現(xiàn)的臨時(shí)實(shí)體對(duì)像或者載入一個(gè)源自數(shù)據(jù)庫的可被編輯的實(shí)體的好機(jī)會(huì)。
在Tapestry 5輸入驗(yàn)證中,當(dāng)用戶在客戶端提交表單時(shí),服務(wù)器端會(huì)執(zhí)行一系列的步驟。
首先,表單呈現(xiàn)時(shí)會(huì)發(fā)出一個(gè)“prepare”通知。
其次,所有的表單域被激活并將從請(qǐng)求中得到相應(yīng)的值,驗(yàn)證它們及(如果有效)保存現(xiàn)有的變化。
對(duì)Tapestry 4的用戶:Tapestry 5不使用Tapestry 4中脆弱的表單刷新(form rewind)方法,而是在表單呈現(xiàn)時(shí)產(chǎn)生一個(gè)存放是否需要處理表單提交信息的隱藏域。
表單域流程處理完后,表單發(fā)出一個(gè)“validate”事件,這是一個(gè)執(zhí)行跨表單驗(yàn)證(還不能公布其詳情)的機(jī)會(huì)。
然后,表單確定是否存在任何Tapestry 5輸入驗(yàn)證錯(cuò)誤。如果存在,表單提交失敗并發(fā)出一個(gè)"failure"事件。如果沒有驗(yàn)證錯(cuò)誤,些時(shí)將發(fā)出一個(gè)"success"事件。
最后,表單發(fā)出一個(gè)"submit"事件(邏輯上,它不考慮成功與否)。
跟蹤驗(yàn)證錯(cuò)誤
一個(gè)與表單關(guān)聯(lián)的就是驗(yàn)證跟蹤器(ValidationTracker),它跟蹤著表單域?qū)?yīng)的所有的用戶輸入與用戶驗(yàn)證錯(cuò)誤。跟蹤器可以通過跟蹤器參數(shù)提供給表單,不過很少用到。
表單(Form)包括兩個(gè)isValid() 和 getHasErrors()方法,用來查看表單驗(yàn)證跟蹤器是否存在任何錯(cuò)誤。
在我們的邏輯中,我們可以記錄驗(yàn)證錯(cuò)誤。表單(Form)包括兩個(gè)不同版本的recordError()方法,一個(gè)是指定一個(gè)表單域(Field,一個(gè)被所有表單元素組件實(shí)現(xiàn)的接口),另外一個(gè)是全局驗(yàn)證錯(cuò)誤("global" errors),與具體的表單域無關(guān)。
在請(qǐng)求間保存數(shù)據(jù)
因?yàn)槠渌膭?dòng)作請(qǐng)求,表單提交的結(jié)果會(huì)向客戶端發(fā)出一個(gè)重定向來重新呈現(xiàn)頁面。驗(yàn)證跟蹤器必須在請(qǐng)求間被持久化地(persistently)保存下來,否則所有的Tapestry 5輸入驗(yàn)證信息會(huì)丟失(表單提供一個(gè)persisten形式的默認(rèn)驗(yàn)證跟蹤器)。
同樣地,組件更新單獨(dú)的表單域也應(yīng)該被持久化。
比如,一個(gè)用來收集用戶名與密碼的登錄頁面,應(yīng)該如下:

東平網(wǎng)站制作公司哪家好,找成都創(chuàng)新互聯(lián)!從網(wǎng)頁設(shè)計(jì)、網(wǎng)站建設(shè)、微信開發(fā)、APP開發(fā)、成都響應(yīng)式網(wǎng)站建設(shè)等網(wǎng)站項(xiàng)目制作,到程序開發(fā),運(yùn)營維護(hù)。成都創(chuàng)新互聯(lián)從2013年開始到現(xiàn)在10年的時(shí)間,我們擁有了豐富的建站經(jīng)驗(yàn)和運(yùn)維經(jīng)驗(yàn),來保證我們的工作的順利進(jìn)行。專注于網(wǎng)站建設(shè)就選成都創(chuàng)新互聯(lián)。
- 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;
- }
- }
因?yàn)镕orm表單提交實(shí)際上是兩個(gè)請(qǐng)求(提交自己,然后重新呈現(xiàn)頁面),所以需要在兩個(gè)請(qǐng)求間持久化保存在_userName屬性里的值。屬性_password同樣需要,除非PasswordField組件從不呈現(xiàn)值。
注意onSuccess()方法不是公共的(public);事件處理方法可以具有任何的可見性,甚至私有的。包可見性(即無可見性修飾)比較常用,這時(shí)它允許組件可被相同包下的測(cè)試用例類測(cè)試。
假如Form先前沒有存在驗(yàn)證錯(cuò)誤,它僅產(chǎn)生一個(gè)"success"事件,這意味著沒有必要在方法的第一行寫上if (_form.getHasErrors()) return;這樣的語句。
最后,注意業(yè)務(wù)邏輯如何與表單驗(yàn)證相關(guān)聯(lián)。UserAuthenticator服務(wù)用來保證userName 和 (文本的) password的有效性。當(dāng)它返回false時(shí),我們用Form組件來記錄一個(gè)錯(cuò)誤。我們提供一個(gè)PasswordField實(shí)例作為它的第一個(gè)參數(shù),這保證了密碼表單域和它的標(biāo)注(label)會(huì)在Form表單重新呈現(xiàn)時(shí)被修飾以表現(xiàn)錯(cuò)誤給用戶看。
Tapestry 5輸入驗(yàn)證的配置表單域及標(biāo)注
頁面模板包含少量的Tapestry 標(biāo)識(shí)(instrumentation):
- ﹤html xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd"﹥
- ﹤head﹥
- ﹤title﹥Login﹤/title﹥
- ﹤/head﹥
- ﹤body﹥
- ﹤h1﹥Please Login﹤/h1﹥
- ﹤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的Form組件負(fù)責(zé)創(chuàng)建form表單提交所需的URL(這個(gè)Tapestry的責(zé)任,不是你的)。
Errors組件必須放在Form里,它將Form組件里表單域的所有錯(cuò)誤信息作為一個(gè)列表輸出,并應(yīng)用一此簡(jiǎn)單的樣式使得結(jié)果更顯眼。
每一個(gè)表單域組件,比如TextField,與Label組件成對(duì)。Label將呈現(xiàn)一個(gè)與表單域相連的<label>元素。這個(gè)組件對(duì)方便使用非常重要,特別對(duì)那些有視覺障礙(殘疾)的用戶。它意味著你可以能過點(diǎn)擊標(biāo)注(label)文本將光標(biāo)移動(dòng)到相應(yīng)的表單域中。Label組件的for參數(shù)即是一組件的id。
對(duì)于TextField,我們提供了一個(gè)組件id為userName。我們可以指定一個(gè)value參數(shù),默認(rèn)情況下這個(gè)value參數(shù)是匹配TextField的id,TextField的id又對(duì)應(yīng)于組件容器(Login頁)的一個(gè)屬性(假如這個(gè)屬性存在)。
根據(jù)經(jīng)驗(yàn),你通常應(yīng)該為表單域指定一個(gè)特定的id(這個(gè)id將會(huì)被用來呈現(xiàn)標(biāo)簽的name與id屬性)。允許省略value參數(shù)有利于防止模板變得更加混亂。
用來驗(yàn)證表單域的validate參數(shù)標(biāo)識(shí),是一個(gè)驗(yàn)證器的名字列表。驗(yàn)證器在Tapestry中被配置,可用的驗(yàn)證器都是可擴(kuò)展的。"required"是一個(gè)內(nèi)置驗(yàn)證器的名字,用以保證提交的值不為空串,此外,"minlen"用來保證值具有最小的指定長度。
Validate參數(shù)用t:前綴被放置在Tapestry的命名空間里。這不是嚴(yán)格需要的,只是讓模板有個(gè)良好的格式。然而,在Tapestry命名空間放置Tapestry特定的值保證了模板的有效性。
錯(cuò)誤及修飾Errors and Decorations
注意:這部分并沒有更新到涉及客戶端驗(yàn)證的介紹。
在Tapestry 5輸入驗(yàn)證中,當(dāng)你第一次激活Login頁里,表單域及表單會(huì)被正常呈現(xiàn)等待輸入:
注意這里的Label組件怎樣顯示表單域的文本名字。我們未曾做過任何顯式地配置,組件的id ("User Name" 和 "Password")已經(jīng)轉(zhuǎn)換成"User Name" 和 "Password",倒底發(fā)生了什么?。
如果你就這樣提交了表單,表單域就會(huì)違反了"required"約束,頁面將會(huì)重新顯示以呈現(xiàn)給用戶錯(cuò)誤信息。
這里有兩個(gè)微妙事情,首先,Tapestry跟蹤了所有表單域的所有錯(cuò)誤信息,Errors組件顯示在表單的最頂端;其次,默認(rèn)的驗(yàn)證修飾給標(biāo)注(labels)和表單域的class屬性加上了t-error CSS樣式。Tapestry提供了默認(rèn)的t-error CSS樣式使得它們變紅。
接下來,我們將在user name欄上填值,但不給password欄提供足夠的字符:User name欄正常,僅password欄有一個(gè)錯(cuò)誤存在。PasswordField組件默認(rèn)下通常顯示一空值,另外我們會(huì)看到僅password顯示在…
如果你輸入了足夠的字符后提交,我們會(huì)看到Login頁面是如何將邏輯錯(cuò)誤加入到表單域的錯(cuò)誤里:
這真是天衣無縫,基于應(yīng)用的邏輯錯(cuò)誤看起來感覺就像內(nèi)置驗(yàn)證器的行為。
當(dāng)前標(biāo)題:Tapestry5輸入驗(yàn)證的實(shí)現(xiàn)方法
網(wǎng)站地址:http://m.5511xx.com/article/cdepjsh.html


咨詢
建站咨詢
