`
geszJava
  • 浏览: 33927 次
社区版块
存档分类
最新评论

Grails的Javascript验证DIY

阅读更多
看到Grails的validation标签居然是没实现,一下子大受打击!很郁闷,但是没办法,偶们还是自己来实现一下这个重要的功能把.
Grails的tag其实一般都在\grails-app\taglib下面,可以自行修改源程序来修改tag的表现.validation标签就在ValidationTagLib.groovy这个文件里面.只要修改一下代码就可以了,由于实现过程比较繁杂,直接贴出源代码,需要注意的是:
第一个地方:” import org.geszjava.grails.utils.ChineseProperty as CP;”这条语句,偶是自己写一个类来进行属性名和表单说明的转换,这一步算是偷懒了.有好处也有坏处,好处是不用写那么多Local信息了,直接拿default的来就可以了.坏处是Locale的处理上有问题.当然我现在的项目只支持中文.:),以后有时间可以考虑本地化问题.BTW:grails自己的本地化支持目前好像还没有?不太清楚.呵呵.
第二个地方:”size”这种Type用的是”minLength,maxLength”,而不是原先的intRange,具体怎么回事用脑袋想想也知道:两者在javascript上的实现天差地远.
第三个地方:splitType(),由于有了”minLength,maxLength”这种类型,那么整合的时候当然不能直接写成validationMinLength,maxLength()这样的东东,可以说是个比较严重的错误,所以这里顺便更改了一下
第四个地方: 看看这段代码
switch(vt) {
	                    case 'mask': 
	                    	out << "function ${form}_mask() {";
		                    break;
	                    case 'intRange': 
	                    	out << "function ${form}_intRange() {";
	                    	break;
	                    case 'floatRange': 
	                    	out << "function ${form}_floatRange() {";
	                    	break;
	                    case 'maxLength': 
	                    	out << "function ${form}_maxlength() {";
	                    	break;
	                    case 'minLength': 
	                    	out << "function ${form}_minlength() {";
	                    	break;
	                    case 'email':
	                    	out << "function ${form}_email() {";
	                    	break;
	                    case 'creditCard':
	                    	out << "function ${form}_creditCard() {";
	                    	break;
	                    case 'required':
	                    	out << "function ${form}_required() {";
	                    	break;           
	                    default:
	                    	out << "function ${form}_${vt}() {";
	                    	break;
               		}

原先的代码太粗略,minlength和maxlength不能工作,所以写个比较麻烦的代码,其实修改一下那个MAP就可以了,不过那样修改的东西太多了,不合算.


/* Copyright 2004-2005 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT c;pWARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
import java.text.MessageFormat
import org.springframework.validation.Errors;
import org.springframework.context.NoSuchMessageException;
import org.springframework.web.servlet.support.RequestContextUtils as RCU;
import org.codehaus.groovy.grails.commons.GrailsClassUtils as GCU;
import org.geszjava.grails.utils.ChineseProperty as CP;


/**
*  A  tag lib that provides tags to handle validation and errors
*
* @author Graeme Rocher
* @since 17-Jan-2006
*/

class ValidationTagLib {
    /**
     * Checks if the request has errors either for a field or global errors
     */
    def hasErrors = { attrs, body ->
        def model = attrs['model']
        def checkList = []
        if(model) {
            checkList = model.findAll { k,v ->
                grailsApplication.isGrailsDomainClass(v.class)
            }
        }
        if(attrs['bean']) {
            checkList << attrs['bean']
        }
        else {
			if(request.attributeNames) {
				request.attributeNames.each { ra ->
					if(ra) {
                        if(ra instanceof Errors)
                            checkList << ra
                        else if(grailsApplication.isGrailsDomainClass(ra.class))
                            checkList << ra
					}
				}
			}
        }

        for(i in checkList) {
            def errors = null
            if(grailsApplication.isGrailsDomainClass(i.class)) {
                if(i.hasErrors())
                    errors = i.errors
            }
            else if(i instanceof Errors) {
               errors = i
            }
            if(errors) {
                if(attrs['field']) {
                    if(errors.hasFieldErrors(attrs['field'])) {
                        body()
                    }
                }
                else {
                    body()
                }
            }
        }
    }

    /**
     * Loops through each error for either field or global errors
     */
    def eachError = { attrs, body ->
        def model = attrs['model']
        def errorList = []
        if(model) {
            errorList = model.findAll { k,v ->
                grailsApplication.isGrailsDomainClass(v.class)
            }
        }
        if(attrs['bean']) {
            errorList << attrs['bean']
        }
        else {
            request.attributeNames.each {
                def ra = request[it]
                if(ra) {
                    if(ra instanceof Errors)
                        errorList << ra
                    else if(grailsApplication.isGrailsDomainClass(ra.class))
                        errorList << ra
                }
            }
        }

        for(i in errorList) {
            def errors = null
            if(grailsApplication.isGrailsDomainClass(i.class)) {
                if(i.hasErrors())
                    errors = i.errors
            }
            else if(i instanceof Errors) {
               errors = i
            }
            if(errors && errors.hasErrors()) {
                if(attrs['field']) {
                    if(errors.hasFieldErrors(attrs['field'])) {
                        errors.getFieldErrors( attrs["field"] ).each {
                            body(it)
                        }
                    }
                }
                else {
                    errors.allErrors.each {
                        body( it )
                    }
                }
            }
        }
    }

    /**
     * Loops through each error and renders it using one of the supported mechanisms (defaults to "list" if unsupported)
     */
    def renderErrors = { attrs, body ->
        def renderAs = attrs.remove('as')
        if(!renderAs) renderAs = 'list'

        if(renderAs == 'list') {
            out << "<ul>"
            eachError(attrs, {
                out << "<li>"
                message(error:it)
                out << "</li>"
              }
            )
            out << "</ul>"
        }
    }
    /**
     * Resolves a message code for a given error or code from the resource bundle
     */
    def message = { attrs ->
          def messageSource = grailsAttributes
                                .getApplicationContext()
                                .getBean("messageSource")

          def locale = RCU.getLocale(request)

          if(attrs['error']) {
                def error = attrs['error']
                def defaultMessage = ( attrs['default'] ? attrs['default'] : error.defaultMessage )
                def message = messageSource.getMessage( error.code,
                                                        error.arguments,
                                                        defaultMessage,
                                                        locale )
                if(message) {
                    out << message
                }
                else {
                    out << error.code
                }
          }
          if(attrs['code']) {
                def code = attrs['code']
                def defaultMessage = ( attrs['default'] ? attrs['default'] : code )

                def message = messageSource.getMessage( code,
                                                        null,
                                                        defaultMessage,
                                                        locale )
                if(message) {
                    out << message
                }
                else {
                    out << code
                }
          }
    }
    // Maps out how Grails contraints map to Apache commons validators
    static CONSTRAINT_TYPE_MAP = [ email : 'email',
                                             creditCard : 'creditCard',
                                             match : 'mask',
                                             blank: 'required',
                                             nullable: 'required',
                                             maxSize: 'maxLength',
                                             minSize: 'minLength',
                                             range: 'intRange',
                                             size: 'maxLength,minLength',
                                             length: 'maxLength,minLength' ]
    /**
     * Validates a form using Apache commons validator javascript against constraints defined in a Grails
     * domain class
     *
     * TODO: This tag is a work in progress
     修改
     */
    def validate = { attrs, body ->
        def form = attrs["form"]
        def againstClass = attrs["against"]
        if(!form)
            throwTagError("Tag [validate] is missing required attribute [form]")

        if(!againstClass) {
            againstClass = form.substring(0,1).toUpperCase() + form.substring(1)
        }

        def app = grailsAttributes.getGrailsApplication()
        def dc = app.getGrailsDomainClass(againstClass)

        if(!dc)
            throwTagError("Tag [validate] could not find a domain class to validate against for name [${againstClass}]")

        def constrainedProperties = dc.constrainedProperties.collect { k,v -> return v }
        def appliedConstraints = []

        constrainedProperties.each {
           appliedConstraints += it.collect{ it.appliedConstraints }
        }

        appliedConstraints = appliedConstraints.flatten()
        def fieldValidations = [:]
        appliedConstraints.each {

            def validateType = CONSTRAINT_TYPE_MAP[it.name]
            if(validateType) {
                if(fieldValidations[validateType]) {
                    fieldValidations[validateType] << it
                }
                else {
                     fieldValidations[validateType] =  [it]
                }
            }
        }

        out << '<script type="text/javascript">\n'
        def scriptNameUtil = "org/apache/commons/validator/javascript/validateUtilities.js"
            
        def inStreamUtil = getClass().classLoader.getResourceAsStream(scriptNameUtil)
        if(inStreamUtil) {
            out << inStreamUtil.text
        }        
        
        fieldValidations.each { k,v ->
           def validateType = k

           if(validateType) {

                def validateTypes = [validateType]

                if(validateType.contains(",")) {
                    validateTypes = validateType.split(",")
                }

                validateTypes.each { vt ->
                    // import required script
                    def scriptName = "org/apache/commons/validator/javascript/validate" + vt.substring(0,1).toUpperCase() + vt.substring(1) + ".js"
                    def inStream = getClass().classLoader.getResourceAsStream(scriptName)
                    if(inStream) {
                        out << inStream.text
                    }
                    
                    switch(vt) {
	                    case 'mask': 
	                    	out << "function ${form}_mask() {";
		                    break;
	                    case 'intRange': 
	                    	out << "function ${form}_intRange() {";
	                    	break;
	                    case 'floatRange': 
	                    	out << "function ${form}_floatRange() {";
	                    	break;
	                    case 'maxLength': 
	                    	out << "function ${form}_maxlength() {";
	                    	break;
	                    case 'minLength': 
	                    	out << "function ${form}_minlength() {";
	                    	break;
	                    case 'email':
	                    	out << "function ${form}_email() {";
	                    	break;
	                    case 'creditCard':
	                    	out << "function ${form}_creditCard() {";
	                    	break;
	                    case 'required':
	                    	out << "function ${form}_required() {";
	                    	break;           
	                    default:
	                    	out << "function ${form}_${vt}() {";
	                    	break;
               		}
                    
                    //out << "function ${form}_${vt.toLowerCase()}() {"
                    	
                    v.each { constraint ->
                           out << "this.${constraint.propertyName} = new Array("
                           out << "'${constraint.propertyName}'," // the field
                           //out << '"Test message"' // TODO: Resolve the actual message
                           def clazzName = againstClass?.toLowerCase()
                           out << getMessage(vt, clazzName, constraint.propertyName, constraint)

                           switch(vt) {
                                case 'mask': out << ",function() { return '${constraint.regex}'; }";break;
                                case 'intRange': out << ",function() { if(arguments[0]=='min') return ${constraint.range.from}; else return ${constraint.range.to} }";break;
                                case 'floatRange': out << ",function() { if(arguments[0]=='min') return ${constraint.range.from}; else return ${constraint.range.to} }";break;
                                case 'maxLength': 
                                	if (!isSizeConstraint(constraint)) {
	                                	out << ",function() {return ${constraint.maxSize};}";
                                	} else {
                                		out << ",function() {return ${constraint.range.to};}";
                                	}
                                	break;
                                case 'minLength': 
                                	if (!isSizeConstraint(constraint)) {
	                                	out << ",function() {return ${constraint.minSize};}";
                                	} else {
                                		out << ",function() {return ${constraint.range.from};}";
                                	}
                                	break;
                           }
                           out << ');\n'
                    }
                    out << "}\n"
                }
            }
        }
        out << 'function validateForm(form) {\n'
         fieldValidations.each { k,v ->
         	   def splittedTypes = splitType(k);
         	   for (spt in splittedTypes) {
	               def validateType = spt.substring(0,1).toUpperCase() + spt.substring(1)
	               out << "if(!validate${validateType}(form)) return false;\n"
         	   }
         }
        out << 'return true;\n';
        out << '}\n'
      	out << "document.forms['${attrs['form']}'].onsubmit = function() {return validateForm(this);}\n"
        out << '</script>'
    }
    
    //添加
    def static messageMap = [
    	"mask" : "{0}不符合正则表达式[{1}]",
    	"creditCard" : "{0}不是一个合法的信用卡号",
    	"email" : "{0}不是一个合法的Email地址",
    	"intRange" : "{0}不在{1}到{2}之内",
    	"floatRange" : "{0}不在{1}到{2}之内",
    	"maxLength" : "{0}的长度大于{1}",
    	"minLength" : "{0}的长度小于{1}",
    	"required" : "{0}不能为空",
     ]                           
     
     //添加
    def static splitType(type) {
    	 if (type.indexOf(",") >= 0) {
    		 StringTokenizer st = new StringTokenizer(type, ",");
    		 def retList = []
    		 while (st.hasMoreTokens()) {
    			 retList << st.nextToken();
    		 }
    		 return retList;
    	 } else {
    		 return [type];
    	 }
    }
    
    def static isSizeConstraint(constraint) {
    	if (constraint.getClass().getName() == "org.codehaus.groovy.grails.validation.ConstrainedProperty\$SizeConstraint") 
    		return true
    	else return false
    }
     //添加
	def getMessage(vt, clazzName, propertyName, constraint) {
    	def cn = CP.getChinesePropertyName(clazzName + "." + propertyName)
    	if (!cn) cn = propertyName
    	Object[] args = new Object[3]
		args[0] = cn
		def omsg = messageMap[vt]
		if (!omsg) omsg = "存在未知错误"
    	def msg = "";
    	
		switch(vt) {
			case 'email': 
				break
			case 'creditCard': 
				break
			case 'mask': 
				args[1] = constraint.regex
				break
			case 'intRange': 
				args[1] = constraint.range.from
				args[2] = constraint.range.to
				break
			case 'floatRange': 
				args[1] = constraint.range.from
				args[2] = constraint.range.to
				break;
			case 'maxLength': 
				if (!isSizeConstraint(constraint)) {
					args[1] = constraint.maxSize
				} else {
					args[1] = constraint.range.to
				}
				break
			case 'minLength': 
				if (!isSizeConstraint(constraint)) {
					args[1] = constraint.minSize
				} else {
					args[1] = constraint.range.from
				}
 				break				
    	}

		return "\"" + MessageFormat.format(omsg, args) + "\""
    }
}
分享到:
评论

相关推荐

    Grails Grails Grails

    Domain Classes使用Groovy的元编程特性,如属性验证和动态方法,提供数据验证和业务逻辑。 2. **视图(View)**: 视图负责展示数据,通常使用GSP(Grails Server Pages)技术,这是一种结合了HTML和Groovy的模板...

    grails ajax

    描述中的"javascript and ajax using in grails"强调了JavaScript在Grails应用中的重要性。JavaScript是实现Ajax交互的主要语言,通常用于处理用户交互和动态更新页面。Grails提供了与jQuery等流行JavaScript库集成...

    Grails权威指南 Grails权威指南

    《Grails权威指南》是一本全面深入探讨Grails框架的专著,旨在帮助读者掌握这一强大的Web开发工具。Grails是一种基于Groovy语言的开源框架,它为构建现代、高效的应用程序提供了简洁高效的解决方案。本指南针对不同...

    grails中文入门简介

    验证是Web开发中不可或缺的一部分,Grails通过声明约束和验证约束来实现。它支持客户端验证,使得可以在用户提交表单之前校验数据。Grails的国际化支持非常好,开发者可以通过简单的配置来为不同的语言环境定制应用...

    Eclipse下搭建Grails项目

    【Grails项目搭建详解】 Grails是一个基于Groovy语言的开源Web应用框架,它简化了开发过程,尤其适合快速构建动态网站。在Eclipse中搭建Grails项目可能相对复杂,但通过以下步骤,即使是初学者也能顺利进行。 1. *...

    Grails Jquery 集成代码

    在开发Web应用时,将Grails(一个基于Groovy语言的开源全栈式Web应用框架)与JQuery(一个轻量级、高性能的JavaScript库)集成可以极大地提升用户体验和开发效率。下面我们将深入探讨如何在Grails项目中整合JQuery,...

    Grails入门指南 -- 针对grails1.0.4更新

    ### Grails入门指南知识点 #### 一、Grails框架简介 - **背景**: Grails是一个基于Groovy语言的开源Web应用框架,适用于Java平台。它旨在简化开发过程,提高开发效率,尤其受到那些希望保留Java环境同时寻求更高效...

    grails-用户手册

    《Grails用户手册》 Grails,作为一个基于Groovy语言的开源Web应用框架,深受开发者喜爱,它简化了Java开发的复杂性,提供了强大的MVC(Model-View-Controller)架构,以及丰富的插件系统。这份用户手册将帮助你...

    Groovy和Grails配置方法

    验证Grails是否安装成功的方法是在命令行中输入`grails`,如果出现Grails的欢迎信息,则表示安装成功。 **3. 安装Groovy** 最后一步是安装Groovy语言。本文档中的版本为1.5.4,可以从以下地址下载: - 下载地址:...

    Grails中文参考手册

    **Grails 概述** Grails 是一个基于 Groovy 语言的开源 web 应用程序框架,它构建在 Java 平台上,旨在提高开发效率,简化常见 Web 开发任务。Grails 遵循 Model-View-Controller (MVC) 架构模式,允许开发者快速...

    grails-2.4.4.zip

    - **Filters**:在请求处理前或后执行的逻辑,可用于登录验证、日志记录等。 4. **GORM(Grails Object Relational Mapping)** GORM 提供了对数据库的操作接口,使得开发者可以通过面向对象的方式操作数据,减少...

    eclipse开发grails插件

    对于Grails开发,我们需要的是Eclipse中的Grails插件,它能够提供对Grails项目的创建、运行、调试等一系列功能。 **Grails**是基于Groovy语言的全栈式Web开发框架,它借鉴了Ruby on Rails的设计理念,提供了快速...

    第一个grails程序

    总的来说,"第一个grails程序"是一个基础的登录验证系统,展示了Grails如何快速构建Web应用,包括处理用户请求、与数据库交互、实现业务逻辑和视图渲染。这个简单的例子对于初学者来说,是理解Grails框架工作原理和...

    grails login

    **Grails登录系统详解** Grails是一个基于Java的开源Web应用程序框架,它使用Groovy语言进行开发,提供了高效、简洁的编程模型。在Grails中实现用户登录功能是构建任何Web应用的基础,它确保了数据的安全性和用户...

    grails快速开发web

    ### Grails 快速开发 Web 应用程序 #### 一、Grails 概述 Grails 是一种基于 Groovy 的开源应用框架,用于简化 Web 应用程序的开发过程。它采用约定优于配置的原则,这使得开发者可以更快地创建功能丰富的 Web ...

    使用 Grails 快速开发 Web 应用程序

    通过在命令行输入`grails help`验证安装是否成功。 创建Grails应用使用`grails create-app`命令,例如创建名为"Contact"的应用。Grails会自动生成包含默认目录结构的应用程序。目录结构包括`grails-app/conf`存储...

Global site tag (gtag.js) - Google Analytics