?? validationtaglib.groovy
字號:
/* 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 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;/*** 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 args = attrs['args'] def defaultMessage = ( attrs['default'] ? attrs['default'] : code ) def message = messageSource.getMessage( code, args == null ? null : args.toArray(), 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: 'intRange', 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' 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 } out << "function ${form}_${vt}() {" v.each { constraint -> out << "this.${constraint.propertyName} = new Array(" out << "document.forms['${form}'].elements['${constraint.propertyName}']," // the field out << '"Test message"' // TODO: Resolve the actual message 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': out << ",function() { return ${constraint.maxSize}; }";break; case 'minLength': out << ",function() { return ${constraint.minSize}; }";break; } out << ');\n' } out << "}\n" } } } out << 'function validateForm(form) {\n' fieldValidations.each { k,v -> def validateType = k.substring(0,1).toUpperCase() + k.substring(1) out << "if(!validate${validateType}(form)) return false;\n" } out << 'return true;\n'; out << '}\n' // out << "document.forms['${attrs['form']}'].onsubmit = function(e) {return validateForm(this)}\n" out << '</script>' }}
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -