第10章 在Seam 中的JSF 表单校验

10 Seam 中的JSF 表单校验

 

在简单JSF中,校验被定义在视窗:

 

<h:form>

    <h:messages/>

    <div>

        Country:

        <h:inputText value="#{location.country}" required="true">

            <my:validateCountry/>

        </h:inputText>

    </div>

   

    <div>

        Zip code:

        <h:inputText value="#{location.zip}" required="true">

            <my:validateZip/>

        </h:inputText>

    </div>

    <h:commandButton/>

</h:form>

 

在实践中,这种方法通常违反DRYDon't Repeat Yourself)原则,因为实际上大部分“校验”执行的约束是数据模型的一部分,并且所有存在的方法下放到数据库方案(schema)定义。Seam提供对使用Hibernate校验器定义的基于模型约束的支持。

 

让我们开始在我们的Location类上定义我们的约束:

 

public class Location {

    private String country;

    private String zip;

   

    @NotNull

    @Length(max=30)

    public String getCountry() { return country; }

    public void setCountry(String c) { country = c; }

    @NotNull

    @Length(max=6)

    @Pattern("^\d*$")

    public String getZip() { return zip; }

    public void setZip(String z) { zip = z; }

}

 

好的,那是一个象样的首次收获,但是在实践中,使用自定义约束代替内建的Hibernate 校验器中的一个,可能是更优雅:

 

public class Location {

    private String country;

    private String zip;

   

    @NotNull

    @Country

    public String getCountry() { return country; }

    public void setCountry(String c) { country = c; }

    @NotNull

    @ZipCode

    public String getZip() { return zip; }

    public void setZip(String z) { zip = z; }

}

 

无论我们使用那一个方法,我不再需要指定被用在JSF页面的校验类型。作为替代,我们能使用<s:validate>,根据定义在模型对象上的约束进行校验。

 

<h:form>

    <h:messages/>

    <div>

        Country:

        <h:inputText value="#{location.country}" required="true">

            <s:validate/>

        </h:inputText>

    </div>

   

    <div>

        Zip code:

        <h:inputText value="#{location.zip}" required="true">

            <s:validate/>

        </h:inputText>

    </div>

   

    <h:commandButton/>

</h:form>

 

注意:在模型上指定@NotNull,并不能在显示控件上消除required="true"这个必要条件!这个由于一个JSF校验体系结构的限制。

 

这种方法在模型上定义约束,并且在视窗引入了约束违反——一个引人注目的更好的设计。

 

可是,它并不比我们开始使用的更少冗余,所以让我们试试<s:validateAll>

<h:form>

   

    <h:messages/>

    <s:validateAll>

        <div>

            Country:

            <h:inputText value="#{location.country}" required="true"/>

        </div>

        <div>

            Zip code:

            <h:inputText value="#{location.zip}" required="true"/>

        </div>

        <h:commandButton/>

    </s:validateAll>

</h:form>

 

这个标签对表单中的每一个输入只增加了一个<s:validate>。对大型表单而言,它能节省大量键入!

 

现在我们需要做一些事情,当校验失败时显示反馈给用户。通常,我们显示所有消息在表单的顶端。我们真正喜欢的是带着错误的消息紧挨着字段显示(在这简单JSF中这是可能的),高光显示字段和标签(这是不可能的),以及,再加上,紧挨着字段显示一些图像(也不可能)。我们也想为每一个必需的表单字段,紧挨标签显示一个彩色小星号。

 

对我们表单的每一个字段,那是相当多我们需要的功能。 我们不想为在表单上的每一个字段指定高光、图像层、消息和输入字段。

 

所以,作为替代,我们用一个facelets模板指定公共层:

 

<ui:composition xmlns="http://www.w3.org/1999/xhtml"

                xmlns:ui="http://java.sun.com/jsf/facelets"

                xmlns:h="http://java.sun.com/jsf/html"

                xmlns:f="http://java.sun.com/jsf/core"

                xmlns:s="http://jboss.com/products/seam/taglib">

                

    <div>

   

        <s:label styleClass="#{invalid?'error':''}">

            <ui:insert name="label"/>

            <s:span styleClass="required" rendered="#{required}">*</s:span>

        </s:label>

       

        <span class="#{invalid?'error':''}">

            <h:graphicImage value="/img/error.gif" rendered="#{invalid}"/>

            <s:validateAll>

                <ui:insert/>

            </s:validateAll>

        </span>

       

        <s:message styleClass="error"/>

        

    </div>

   

</ui:composition>

 

我们能使用<s:decorate>,为我们表单字段的每个包括这个模板。

 

<h:form>

    <h:messages globalOnly="true"/>

    <s:decorate template="edit.xhtml">

        <ui:define name="label">Country:</ui:define>

        <h:inputText value="#{location.country}" required="true"/>

    </s:decorate>

   

    <s:decorate template="edit.xhtml">

    <ui:define name="label">Zip code:</ui:define>

        <h:inputText value="#{location.zip}" required="true"/>

    </s:decorate>

    <h:commandButton/>

</h:form>

 

最后,当用户在表单的四处导航时,我们能使用RichFaces Ajax显示校验消息。

 

<h:form>

    <h:messages globalOnly="true"/>

    <s:decorate id="countryDecoration" template="edit.xhtml">

        <ui:define name="label">Country:</ui:define>

        <h:inputText value="#{location.country}" required="true">

            <a:support event="onblur" reRender="countryDecoration" bypassUpdates="true"/>

        </h:inputText>

    </s:decorate>

   

    <s:decorate id="zipDecoration" template="edit.xhtml">

        <ui:define name="label">Zip code:</ui:define>

        <h:inputText value="#{location.zip}" required="true">

            <a:support event="onblur" reRender="zipDecoration" bypassUpdates="true"/>

        </h:inputText>

    </s:decorate>

    <h:commandButton/>

</h:form>

 

为页面上重要的控件定义明确的id是好的风格,特别是如果你想使用一些Selenium类工具包来对UI做自动测试。如果你没有提供明确的idJSF会产生它们,但是,如果你改变了在页面上的任何事,产生的值也会改变。

 

<h:form id="form">

    <h:messages globalOnly="true"/>

    <s:decorate id="countryDecoration" template="edit.xhtml">

       <ui:define name="label">Country:</ui:define>

        <h:inputText id="country" value="#{location.country}" required="true">

            <a:support event="onblur" reRender="countryDecoration" bypassUpdates="true"/>

        </h:inputText>

    </s:decorate>

   

    <s:decorate id="zipDecoration" template="edit.xhtml">

        <ui:define name="label">Zip code:</ui:define>

        <h:inputText id="zip" value="#{location.zip}" required="true">

            <a:support event="onblur" reRender="zipDecoration" bypassUpdates="true"/>

        </h:inputText>

    </s:decorate>

    <h:commandButton/>

</h:form>

 

 

如果当校验失败时,你想指定一个不同的消息显示?你能和Hibernate校验器一起使用Seam消息束(所有象在消息内的EL表达式,每视窗消息束)???:

 

public class Location {

    private String name;

    private String zip;

   

    // Getters and setters for name

    @NotNull

    @Length(max=6)

    @ZipCode(message="#{messages['location.zipCode.invalid']}")

    public String getZip() { return zip; }

    public void setZip(String z) { zip = z; }

}

 

 

location.zipCode.invalid = The zip code is not valid for #{location.name}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值