Tapestry的数据校验功能

Tapestry表单验证
本文介绍了一种改进的Tapestry表单验证方法,针对多个提交按钮的情况,提出了解决方案,包括移除页面配置、监听方法中的验证及错误显示。

Tapestry的数据校验功能 

数据校验是Web应用的一个很重要的功能。
tapestry支持配置式的数据校验,通过使用Delegate、FieldLabel和TextField对数据的显示进行修饰。在page文件中对各输入数据的校验规则进行配置。
可以使用系统提供的Validator。出错信息也提供了多种语言的版本,很方便。
但是问题是:如果表单有多个Submit按钮,不同的按钮需要的校验规则不同,此时该如何做?
众多的web开源框架都存在这样的问题,包括Struts、spring等。
我觉得表单的校验规则应当基于每个提交动作进行配置,而不是基于表单的所有提交动作。
这个现象普遍存在我觉得很奇怪,难道老外做的页面都只有一个提交按钮?
Matt Raible在使用struts中也遇到这个问题,他的解决办法是用javascript给按钮增加onclick代码。这种做法不是太好。

一个想法是取消在page文件中对数据校验的设置,改为在监听方法中调用系统提供的校验器进行校验。然后将错误信息记录于delegate。
如以下代码:
         StringValidator stringValidator = new StringValidator();
         stringValidator.setMinimumLength(6);
         stringValidator.setRequired(true);
         try {
         stringValidator.toObject((IFormComponent) this
         .getComponent("username"), getUsername());
         } catch (ValidatorException ex) {         delegate.record((IFormComponent)this.getComponent("username"),
ex.getLocalizedMessage());
         }

但这么作丧失了配置的便利性。

现在正深入研究如何在tapestry更好地解决这个问题......

目前我的做法如下:
1,page中删除对各个输入域的校验配置,配置form的focus为true以便校验失败时自动聚焦到出错的输入域,注意页面必须使用Body组件;
   
<component id="loginForm" type="Form">
        <binding name="delegate" value="bean:delegate"/>
        <binding name="focus" value="true"/>       
    </component>

2,在各个监听方法中对需要校验的输入域调用系统的validator进行校验;
   
public static boolean required(ValidationDelegate delegate,
            IFormComponent component, String value) {
        boolean success = true;
        StringValidator validator = new StringValidator();
        validator.setRequired(true);
        try {
            validator.toObject(component, value);
        } catch (ValidatorException ex) {
            success = false;
            delegate.record(component, ex.getLocalizedMessage());
            delegate.registerForFocus(component, 0);
        }
        return success;
    }
    以上是对“必须”校验的简单封装,其中加粗一行是为了form聚焦用。
    其它校验都可以分别进行类似的封装。
    监听方法中可以这么调用各校验方法后,然后检查delegate是否有校验错误而进行不同的处理。通常的处理是如果有错误,则返回当前页面,否则进行相应的业务逻辑。
3,校验错误信息的显示
提供了一个ShowError组件:
protected void renderComponent(IMarkupWriter writer, IRequestCycle cycle) {
        if (cycle.isRewinding()) {
            return;
        }
        IValidationDelegate delegate = getDelegate();
        if (delegate == null || !delegate.getHasErrors()) {
            return;
        } else {
            List fieldTrackings = delegate.getFieldTracking();
            for (int i = 0; fieldTrackings != null && i < fieldTrackings.size(); i++) {
                IFieldTracking fieldTracking = (IFieldTracking) fieldTrackings
                        .get(i);
                if (fieldTracking.isInError()) {
                    writer.begin("label");
                    writer.attribute("for", fieldTracking.getFieldName());
                    writer.begin("span");
                    writer
                            .attribute("style",
                                    "font-weight: normal; text-align: left; color: rgb(255, 0, 0); cursor: pointer;");
                    writer.print(fieldTracking.getErrorRenderer().toString());
                    writer.end();
                    writer.end();
                    writer.printRaw("<br>");
                }
            }
            return;
        }
    }

实现的功能就是鼠标移动到每条错误信息上显示手形,点击鼠标自动聚焦到相关输入域上。

4,校验失败的输入域的样式修改
参考betterpetshop
    public void writeAttributes(IMarkupWriter writer, IRequestCycle cycle,
            IFormComponent component, IValidator validator) {
        if (isInError(component)) {
            writer.attribute("style",
                    "color: White; background-color: #EC6233;");
        }
    }

    public void writeSuffix(IMarkupWriter writer, IRequestCycle cycle,
            IFormComponent component, IValidator validator) {
        if (isInError(component)) {
            writer.print(" ");
            writer.beginEmpty("img");
            writer.attribute("src", "./imgs/bzzt_wrong.gif");
            writer.attribute("height", 16);
            writer.attribute("width", 16);
        }
    }

    public void writeLabelPrefix(IFormComponent component,
            IMarkupWriter writer, IRequestCycle cycle) {
        if (isInError(component)) {
            writer.begin("span");
            writer.attribute("style", "color: #EC6233;");
        }
    }

    public void writeLabelSuffix(IFormComponent component,
            IMarkupWriter writer, IRequestCycle cycle) {
        if (isInError(component))
            writer.end();
    }

这么一来,关于校验处理和错误信息显示基本上搞定了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值