Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Ready for 0.1 release.

  • Loading branch information...
commit 20031ecbbdcb9b2d00f6d94bb4eba2797d559d00 1 parent e2489a3
@limcheekin authored
Showing with 111 additions and 634 deletions.
  1. 0  {grails-app/domain/org/grails/jquery/validation/ui → bak}/DummyDomain.groovy
  2. 0  {grails-app/controllers/org/grails/jquery/validation/ui → bak}/DummyDomainController.groovy
  3. 0  {grails-app/controllers/org/grails/jquery/validation/ui → bak}/ProcessElementCommand.groovy
  4. 0  {grails-app/controllers/org/grails/jquery/validation/ui → bak}/UserController.groovy
  5. 0  {grails-app/views → bak}/dummyDomain/create.gsp
  6. 0  {grails-app/views → bak}/dummyDomain/edit.gsp
  7. 0  {grails-app/views → bak}/dummyDomain/list.gsp
  8. 0  {grails-app/views → bak}/dummyDomain/show.gsp
  9. 0  {grails-app/views → bak}/index.gsp
  10. +0 −58 grails-app/i18n/messages.properties
  11. +8 −7 grails-app/taglib/org/grails/jquery/validation/ui/JQueryValidationUiTagLib.groovy
  12. +62 −0 scripts/InstallSampleapp.groovy
  13. 0  { → src/sample-app}/grails-app/controllers/org/grails/jquery/validation/ui/PersonController.groovy
  14. 0  { → src/sample-app}/grails-app/domain/org/grails/jquery/validation/ui/Address.groovy
  15. +1 −1  { → src/sample-app}/grails-app/domain/org/grails/jquery/validation/ui/Person.groovy
  16. +7 −0 src/sample-app/grails-app/i18n/messages.properties
  17. +10 −10 { → src/sample-app}/grails-app/views/person/_createAndEdit.gsp
  18. +1 −1  { → src/sample-app}/grails-app/views/person/create.gsp
  19. +5 −34 { → src/sample-app}/grails-app/views/person/edit.gsp
  20. 0  { → src/sample-app}/grails-app/views/person/list.gsp
  21. 0  { → src/sample-app}/grails-app/views/person/show.gsp
  22. +0 −98 src/templates/scaffolding/Controller.groovy
  23. +0 −65 src/templates/scaffolding/create.gsp
  24. +0 −64 src/templates/scaffolding/edit.gsp
  25. +0 −61 src/templates/scaffolding/list.gsp
  26. +0 −171 src/templates/scaffolding/renderEditor.template
  27. +0 −64 src/templates/scaffolding/show.gsp
  28. +17 −0 test/integration/org/grails/jquery/validation/ui/ConstraintsRetrieveTests.groovy
View
0  ...rg/grails/jquery/validation/ui/DummyDomain.groovy → bak/DummyDomain.groovy
File renamed without changes
View
0  ...jquery/validation/ui/DummyDomainController.groovy → bak/DummyDomainController.groovy
File renamed without changes
View
0  ...jquery/validation/ui/ProcessElementCommand.groovy → bak/ProcessElementCommand.groovy
File renamed without changes
View
0  ...grails/jquery/validation/ui/UserController.groovy → bak/UserController.groovy
File renamed without changes
View
0  grails-app/views/dummyDomain/create.gsp → bak/dummyDomain/create.gsp
File renamed without changes
View
0  grails-app/views/dummyDomain/edit.gsp → bak/dummyDomain/edit.gsp
File renamed without changes
View
0  grails-app/views/dummyDomain/list.gsp → bak/dummyDomain/list.gsp
File renamed without changes
View
0  grails-app/views/dummyDomain/show.gsp → bak/dummyDomain/show.gsp
File renamed without changes
View
0  grails-app/views/index.gsp → bak/index.gsp
File renamed without changes
View
58 grails-app/i18n/messages.properties
@@ -1,58 +0,0 @@
-default.doesnt.match.message=Property [{0}] of class [{1}] with value [{2}] does not match the required pattern [{3}]
-default.invalid.url.message=Property [{0}] of class [{1}] with value [{2}] is not a valid URL
-default.invalid.creditCard.message=Property [{0}] of class [{1}] with value [{2}] is not a valid credit card number
-default.invalid.email.message=Property [{0}] of class [{1}] with value [{2}] is not a valid e-mail address
-default.invalid.range.message=Property [{0}] of class [{1}] with value [{2}] does not fall within the valid range from [{3}] to [{4}]
-default.invalid.size.message=Property [{0}] of class [{1}] with value [{2}] does not fall within the valid size range from [{3}] to [{4}]
-default.invalid.max.message=Property [{0}] of class [{1}] with value [{2}] exceeds maximum value [{3}]
-default.invalid.min.message=Property [{0}] of class [{1}] with value [{2}] is less than minimum value [{3}]
-default.invalid.max.size.message=Property [{0}] of class [{1}] with value [{2}] exceeds the maximum size of [{3}]
-default.invalid.min.size.message=Property [{0}] of class [{1}] with value [{2}] is less than the minimum size of [{3}]
-default.invalid.validator.message=Property [{0}] of class [{1}] with value [{2}] does not pass custom validation
-default.not.inlist.message=Property [{0}] of class [{1}] with value [{2}] is not contained within the list [{3}]
-default.blank.message=Property [{0}] of class [{1}] cannot be blank
-default.not.equal.message=Property [{0}] of class [{1}] with value [{2}] cannot equal [{3}]
-default.null.message=Property [{0}] of class [{1}] cannot be null
-default.not.unique.message=Property [{0}] of class [{1}] with value [{2}] must be unique
-
-default.paginate.prev=Previous
-default.paginate.next=Next
-default.boolean.true=True
-default.boolean.false=False
-default.date.format=yyyy-MM-dd HH:mm:ss z
-default.number.format=0
-
-default.created.message={0} {1} created
-default.updated.message={0} {1} updated
-default.deleted.message={0} {1} deleted
-default.not.deleted.message={0} {1} could not be deleted
-default.not.found.message={0} not found with id {1}
-default.optimistic.locking.failure=Another user has updated this {0} while you were editing
-
-default.home.label=Home
-default.list.label={0} List
-default.add.label=Add {0}
-default.new.label=New {0}
-default.create.label=Create {0}
-default.show.label=Show {0}
-default.edit.label=Edit {0}
-
-default.button.create.label=Create
-default.button.edit.label=Edit
-default.button.update.label=Update
-default.button.delete.label=Delete
-default.button.delete.confirm.message=Are you sure?
-
-# Data binding errors. Use "typeMismatch.$className.$propertyName to customize (eg typeMismatch.Book.author)
-typeMismatch.java.net.URL=Property {0} must be a valid URL
-typeMismatch.java.net.URI=Property {0} must be a valid URI
-typeMismatch.java.util.Date=Property {0} must be a valid Date
-typeMismatch.java.lang.Double=Property {0} must be a valid number
-typeMismatch.java.lang.Integer=Property {0} must be a valid number
-typeMismatch.java.lang.Long=Property {0} must be a valid number
-typeMismatch.java.lang.Short=Property {0} must be a valid number
-typeMismatch.java.math.BigDecimal=Property {0} must be a valid number
-typeMismatch.java.math.BigInteger=Property {0} must be a valid number
-
-#vacationRequest.VacationRequest.employeeName.blank=Custom Blank 1
-#vacationRequest.employeeName.blank=Custom Blank 2
View
15 grails-app/taglib/org/grails/jquery/validation/ui/JQueryValidationUiTagLib.groovy
@@ -84,7 +84,7 @@ class JQueryValidationUiTagLib {
}
def renderErrors = { attrs, body ->
- def renderErrorsOnTop = grailsApplication.config.jqueryValidationUi.get("renderErrorsOnTop", true)
+ def renderErrorsOnTop = attrs.render ? Boolean.valueOf(attrs.render) : grailsApplication.config.jqueryValidationUi.get("renderErrorsOnTop", true)
if (renderErrorsOnTop) {
String qTipClasses = grailsApplication.config.jqueryValidationUi.qTip.classes?:""
String style = attrs.remove("style")?:''
@@ -148,12 +148,13 @@ out << """
def alsoProperties = attrs.remove("also")
def notProperties = attrs.remove("not")
String form = attrs.remove("form")
- def jQueryUiStyle = grailsApplication.config.jqueryValidationUi.qTip.get("jQueryUiStyle", false)
- String qTipClasses = grailsApplication.config.jqueryValidationUi.qTip.classes?:""
- String errorClass = grailsApplication.config.jqueryValidationUi.errorClass?:"error"
- String validClass = grailsApplication.config.jqueryValidationUi.validClass?:"valid"
- def onsubmit = grailsApplication.config.jqueryValidationUi.get("onsubmit", true)
- def renderErrorsOnTop = grailsApplication.config.jqueryValidationUi.get("renderErrorsOnTop", true)
+ def config = grailsApplication.config.jqueryValidationUi
+ def jQueryUiStyle = config.qTip.get("jQueryUiStyle", false)
+ String qTipClasses = config.qTip.classes?:""
+ String errorClass = attrs.errorClass?:config.errorClass?:"error"
+ String validClass = attrs.validClass?:config.validClass?:"valid"
+ def onsubmit = attrs.onsubmit ? Boolean.valueOf(attrs.onsubmit) : config.get("onsubmit", true)
+ def renderErrorsOnTop = attrs.renderErrorsOnTop ? Boolean.valueOf(attrs.renderErrorsOnTop) : config.get("renderErrorsOnTop", true)
String renderErrorsOptions
if (!forClass) {
throwTagError("${TAG_ERROR_PREFIX}Tag missing required attribute [for]")
View
62 scripts/InstallSampleapp.groovy
@@ -0,0 +1,62 @@
+/* Copyright 2010 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 WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+/**
+*
+*
+* @author <a href='mailto:limcheekin@vobject.com'>Lim Chee Kin</a>
+*
+* @since 0.1
+*
+*/
+
+includeTargets << grailsScript("Init")
+
+target(main: "Install person sample application") {
+ ant.copy (todir:"${basedir}/grails-app/views", overwrite: true) {
+ fileset dir:"${jqueryValidationUiPluginDir}/src/sample-app/grails-app/views"
+ }
+
+ ant.copy (todir:"${basedir}/grails-app/controllers", overwrite: true) {
+ fileset dir:"${jqueryValidationUiPluginDir}/src/sample-app/grails-app/controllers"
+ }
+
+ ant.copy (todir:"${basedir}/grails-app/domain", overwrite: true) {
+ fileset dir:"${jqueryValidationUiPluginDir}/src/sample-app/grails-app/domain"
+ }
+
+ updateMessages(jqueryValidationUiPluginDir)
+}
+
+setDefaultTarget(main)
+
+private void updateMessages(def pluginBasedir) {
+ def messagesFile = new File(basedir, 'grails-app/i18n/messages.properties')
+ if (messagesFile.exists() && messagesFile.text.indexOf("person") == -1) {
+ messagesFile.withWriterAppend { messagesFileWriter ->
+ messagesFileWriter.writeLine('')
+ new File("${pluginBasedir}/src/sample-app/grails-app/i18n/messages.properties").eachLine { line ->
+ messagesFileWriter.writeLine(line)
+ }
+ }
+ ant.echo '''
+******************************************************************
+* Your grails-app/i18n/messages.properties has been updated with *
+* default messages of the Person Sample Application; *
+* please verify that the values are correct. *
+******************************************************************
+ '''
+ }
+}
View
0  ...ails/jquery/validation/ui/PersonController.groovy → ...ails/jquery/validation/ui/PersonController.groovy
File renamed without changes
View
0  ...in/org/grails/jquery/validation/ui/Address.groovy → ...in/org/grails/jquery/validation/ui/Address.groovy
File renamed without changes
View
2  ...ain/org/grails/jquery/validation/ui/Person.groovy → ...ain/org/grails/jquery/validation/ui/Person.groovy
@@ -7,6 +7,6 @@ class Person {
static embedded = ['homeAddress', 'workAddress']
static constraints = {
- name blank:false, nullable:false
+ name blank:false
}
}
View
7 src/sample-app/grails-app/i18n/messages.properties
@@ -0,0 +1,7 @@
+#Added by the JQuery Validation UI plugin: Customized messages for the person sample app
+person.name.blank=Person Name cannot be blank.
+address.code.nullable=Address Code cannot be blank.
+address.number.nullable=Address Number cannot be blank.
+# For server side validation
+person.workAddress.nullable=Work Address cannot be blank.
+person.homeAddress.nullable=Home Address cannot be blank.
View
20 grails-app/views/person/_createAndEdit.gsp → ...le-app/grails-app/views/person/_createAndEdit.gsp
@@ -3,14 +3,14 @@
<tbody>
<tr class="prop">
<td valign="top" class="name">
- <label for="name"><g:message code="person.name.label" default="Name" /></label>
+ <label for="name"><g:message code="person.name.label" default="Person Name" /></label>
</td>
<td valign="top" class="value ${hasErrors(bean: personInstance, field: 'name', 'errors')}">
<g:textField name="name" value="${personInstance?.name}" />
</td>
<td>
<g:if test="${hasErrors(bean: personInstance, field: 'name', 'errors')}">
- <jqvalui:renderError for="name" style="margin-left: 5px; margin-top: -21px">
+ <jqvalui:renderError for="name" style="margin-top: -5px">
<g:eachError bean="${personInstance}" field="name"><g:message error="${it}" /></g:eachError>
</jqvalui:renderError>
</g:if>
@@ -19,14 +19,14 @@
<tr class="prop">
<td valign="top" class="name">
- <label for="workAddress.code"><g:message code="address.code.label" default="Code" /></label>
+ <label for="workAddress.code"><g:message code="workAddress.code.label" default="Work Address Code" /></label>
</td>
<td valign="top" class="value ${hasErrors(bean: personInstance?.workAddress, field: 'code', 'errors')}">
<g:textField name="workAddress.code" value="${personInstance?.workAddress?.code}" />
</td>
<td>
<g:if test="${hasErrors(bean: personInstance, field: 'workAddress.code', 'errors')}">
- <jqvalui:renderError for="workAddress.code" style="margin-left: 5px; margin-top: -21px">
+ <jqvalui:renderError for="workAddress.code" style="margin-top: -5px">
<g:eachError bean="${personInstance}" field="workAddress.code"><g:message error="${it}" /></g:eachError>
</jqvalui:renderError>
</g:if>
@@ -35,14 +35,14 @@
<tr class="prop">
<td valign="top" class="name">
- <label for="workAddress.number"><g:message code="address.number.label" default="Number" /></label>
+ <label for="workAddress.number"><g:message code="workAddress.number.label" default="Work Address Number" /></label>
</td>
<td valign="top" class="value ${hasErrors(bean: personInstance?.workAddress, field: 'number', 'errors')}">
<g:textField name="workAddress.number" value="${fieldValue(bean: personInstance?.workAddress, field: 'number')}" />
</td>
<td>
<g:if test="${hasErrors(bean: personInstance, field: 'workAddress.number', 'errors')}">
- <jqvalui:renderError for="workAddress.number" style="margin-left: 5px; margin-top: -21px">
+ <jqvalui:renderError for="workAddress.number" style="margin-top: -5px">
<g:eachError bean="${personInstance}" field="workAddress.number"><g:message error="${it}" /></g:eachError>
</jqvalui:renderError>
</g:if>
@@ -50,14 +50,14 @@
</tr>
<tr class="prop">
<td valign="top" class="name">
- <label for="homeAddress.code"><g:message code="address.code.label" default="Code" /></label>
+ <label for="homeAddress.code"><g:message code="homeAddress.code.label" default="Home Address Code" /></label>
</td>
<td valign="top" class="value ${hasErrors(bean: personInstance?.homeAddress, field: 'code', 'errors')}">
<g:textField name="homeAddress.code" value="${personInstance?.homeAddress?.code}" />
</td>
<td>
<g:if test="${hasErrors(bean: personInstance, field: 'homeAddress.code', 'errors')}">
- <jqvalui:renderError for="homeAddress.code" style="margin-left: 5px; margin-top: -21px">
+ <jqvalui:renderError for="homeAddress.code" style="margin-top: -5px">
<g:eachError bean="${personInstance}" field="homeAddress.code"><g:message error="${it}" /></g:eachError>
</jqvalui:renderError>
</g:if>
@@ -66,14 +66,14 @@
<tr class="prop">
<td valign="top" class="name">
- <label for="homeAddress.number"><g:message code="address.number.label" default="Number" /></label>
+ <label for="homeAddress.number"><g:message code="homeAddress.number.label" default="Home Address Number" /></label>
</td>
<td valign="top" class="value ${hasErrors(bean: personInstance?.homeAddress, field: 'number', 'errors')}">
<g:textField name="homeAddress.number" value="${fieldValue(bean: personInstance?.homeAddress, field: 'number')}" />
</td>
<td>
<g:if test="${hasErrors(bean: personInstance, field: 'homeAddress.number', 'errors')}">
- <jqvalui:renderError for="homeAddress.number" style="margin-left: 5px; margin-top: -21px">
+ <jqvalui:renderError for="homeAddress.number" style="margin-top: -5px">
<g:eachError bean="${personInstance}" field="homeAddress.number"><g:message error="${it}" /></g:eachError>
</jqvalui:renderError>
</g:if>
View
2  grails-app/views/person/create.gsp → src/sample-app/grails-app/views/person/create.gsp
@@ -8,7 +8,7 @@
<g:javascript library="jquery" plugin="jquery"/>
<jqval:resources />
<jqvalui:resources />
- <jqvalui:renderValidationScript for="org.grails.jquery.validation.ui.Person" also="homeAddress, workAddress" form="personForm"/>
+ <jqvalui:renderValidationScript for="org.grails.jquery.validation.ui.Person" also="homeAddress, workAddress" />
</head>
<body>
<div class="nav">
View
39 grails-app/views/person/edit.gsp → src/sample-app/grails-app/views/person/edit.gsp
@@ -7,6 +7,10 @@
<meta name="layout" content="main" />
<g:set var="entityName" value="${message(code: 'person.label', default: 'Person')}" />
<title><g:message code="default.edit.label" args="[entityName]" /></title>
+ <g:javascript library="jquery" plugin="jquery"/>
+ <jqval:resources />
+ <jqvalui:resources />
+ <jqvalui:renderValidationScript for="org.grails.jquery.validation.ui.Person" also="homeAddress, workAddress" />
</head>
<body>
<div class="nav">
@@ -27,40 +31,7 @@
<g:form method="post" >
<g:hiddenField name="id" value="${personInstance?.id}" />
<g:hiddenField name="version" value="${personInstance?.version}" />
- <div class="dialog">
- <table>
- <tbody>
-
- <tr class="prop">
- <td valign="top" class="name">
- <label for="homeAddress"><g:message code="person.homeAddress.label" default="Home Address" /></label>
- </td>
- <td valign="top" class="value ${hasErrors(bean: personInstance, field: 'homeAddress', 'errors')}">
-
- </td>
- </tr>
-
- <tr class="prop">
- <td valign="top" class="name">
- <label for="name"><g:message code="person.name.label" default="Name" /></label>
- </td>
- <td valign="top" class="value ${hasErrors(bean: personInstance, field: 'name', 'errors')}">
- <g:textField name="name" value="${personInstance?.name}" />
- </td>
- </tr>
-
- <tr class="prop">
- <td valign="top" class="name">
- <label for="workAddress"><g:message code="person.workAddress.label" default="Work Address" /></label>
- </td>
- <td valign="top" class="value ${hasErrors(bean: personInstance, field: 'workAddress', 'errors')}">
-
- </td>
- </tr>
-
- </tbody>
- </table>
- </div>
+ <g:render template="createAndEdit" />
<div class="buttons">
<span class="button"><g:actionSubmit class="save" action="update" value="${message(code: 'default.button.update.label', default: 'Update')}" /></span>
<span class="button"><g:actionSubmit class="delete" action="delete" value="${message(code: 'default.button.delete.label', default: 'Delete')}" onclick="return confirm('${message(code: 'default.button.delete.confirm.message', default: 'Are you sure?')}');" /></span>
View
0  grails-app/views/person/list.gsp → src/sample-app/grails-app/views/person/list.gsp
File renamed without changes
View
0  grails-app/views/person/show.gsp → src/sample-app/grails-app/views/person/show.gsp
File renamed without changes
View
98 src/templates/scaffolding/Controller.groovy
@@ -1,98 +0,0 @@
-<%=packageName ? "package ${packageName}\n\n" : ''%>class ${className}Controller {
-
- static allowedMethods = [save: "POST", update: "POST", delete: "POST"]
-
- def index = {
- redirect(action: "list", params: params)
- }
-
- def list = {
- params.max = Math.min(params.max ? params.int('max') : 10, 100)
- [${propertyName}List: ${className}.list(params), ${propertyName}Total: ${className}.count()]
- }
-
- def create = {
- def ${propertyName} = new ${className}()
- ${propertyName}.properties = params
- return [${propertyName}: ${propertyName}]
- }
-
- def save = {
- def ${propertyName} = new ${className}(params)
- if (${propertyName}.save(flush: true)) {
- flash.message = "\${message(code: 'default.created.message', args: [message(code: '${domainClass.propertyName}.label', default: '${className}'), ${propertyName}.id])}"
- redirect(action: "show", id: ${propertyName}.id)
- }
- else {
- render(view: "create", model: [${propertyName}: ${propertyName}])
- }
- }
-
- def show = {
- def ${propertyName} = ${className}.get(params.id)
- if (!${propertyName}) {
- flash.message = "\${message(code: 'default.not.found.message', args: [message(code: '${domainClass.propertyName}.label', default: '${className}'), params.id])}"
- redirect(action: "list")
- }
- else {
- [${propertyName}: ${propertyName}]
- }
- }
-
- def edit = {
- def ${propertyName} = ${className}.get(params.id)
- if (!${propertyName}) {
- flash.message = "\${message(code: 'default.not.found.message', args: [message(code: '${domainClass.propertyName}.label', default: '${className}'), params.id])}"
- redirect(action: "list")
- }
- else {
- return [${propertyName}: ${propertyName}]
- }
- }
-
- def update = {
- def ${propertyName} = ${className}.get(params.id)
- if (${propertyName}) {
- if (params.version) {
- def version = params.version.toLong()
- if (${propertyName}.version > version) {
- <% def lowerCaseName = grails.util.GrailsNameUtils.getPropertyName(className) %>
- ${propertyName}.errors.rejectValue("version", "default.optimistic.locking.failure", [message(code: '${domainClass.propertyName}.label', default: '${className}')] as Object[], "Another user has updated this ${className} while you were editing")
- render(view: "edit", model: [${propertyName}: ${propertyName}])
- return
- }
- }
- ${propertyName}.properties = params
- if (!${propertyName}.hasErrors() && ${propertyName}.save(flush: true)) {
- flash.message = "\${message(code: 'default.updated.message', args: [message(code: '${domainClass.propertyName}.label', default: '${className}'), ${propertyName}.id])}"
- redirect(action: "show", id: ${propertyName}.id)
- }
- else {
- render(view: "edit", model: [${propertyName}: ${propertyName}])
- }
- }
- else {
- flash.message = "\${message(code: 'default.not.found.message', args: [message(code: '${domainClass.propertyName}.label', default: '${className}'), params.id])}"
- redirect(action: "list")
- }
- }
-
- def delete = {
- def ${propertyName} = ${className}.get(params.id)
- if (${propertyName}) {
- try {
- ${propertyName}.delete(flush: true)
- flash.message = "\${message(code: 'default.deleted.message', args: [message(code: '${domainClass.propertyName}.label', default: '${className}'), params.id])}"
- redirect(action: "list")
- }
- catch (org.springframework.dao.DataIntegrityViolationException e) {
- flash.message = "\${message(code: 'default.not.deleted.message', args: [message(code: '${domainClass.propertyName}.label', default: '${className}'), params.id])}"
- redirect(action: "show", id: params.id)
- }
- }
- else {
- flash.message = "\${message(code: 'default.not.found.message', args: [message(code: '${domainClass.propertyName}.label', default: '${className}'), params.id])}"
- redirect(action: "list")
- }
- }
-}
View
65 src/templates/scaffolding/create.gsp
@@ -1,65 +0,0 @@
-<% import grails.persistence.Event %>
-<% import org.codehaus.groovy.grails.plugins.PluginManagerHolder %>
-<%=packageName%>
-<html>
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
- <meta name="layout" content="main" />
- <g:set var="entityName" value="\${message(code: '${domainClass.propertyName}.label', default: '${className}')}" />
- <title><g:message code="default.create.label" args="[entityName]" /></title>
- <g:javascript library="jquery" plugin="jquery"/>
- <jqval:resources />
- <jqvalui:resources />
- <jqvalui:renderValidationScript for="${domainClass.fullName}" />
- </head>
- <body>
- <div class="nav">
- <span class="menuButton"><a class="home" href="\${createLink(uri: '/')}"><g:message code="default.home.label"/></a></span>
- <span class="menuButton"><g:link class="list" action="list"><g:message code="default.list.label" args="[entityName]" /></g:link></span>
- </div>
- <div class="body">
- <h1><g:message code="default.create.label" args="[entityName]" /></h1>
- <g:if test="\${flash.message}">
- <div class="message">\${flash.message}</div>
- </g:if>
- <g:hasErrors bean="\${${propertyName}}">
- <div class="errors">
- <g:renderErrors bean="\${${propertyName}}" as="list" />
- </div>
- </g:hasErrors>
- <g:form action="save" <%= multiPart ? ' enctype="multipart/form-data"' : '' %>>
- <div class="dialog">
- <table>
- <tbody>
- <% excludedProps = Event.allEvents.toList() << 'version' << 'id' << 'dateCreated' << 'lastUpdated'
- persistentPropNames = domainClass.persistentProperties*.name
- props = domainClass.properties.findAll { persistentPropNames.contains(it.name) && !excludedProps.contains(it.name) }
- Collections.sort(props, comparator.constructors[0].newInstance([domainClass] as Object[]))
- display = true
- boolean hasHibernate = PluginManagerHolder.pluginManager.hasGrailsPlugin('hibernate')
- props.each { p ->
- if (!Collection.class.isAssignableFrom(p.type)) {
- if (hasHibernate) {
- cp = domainClass.constrainedProperties[p.name]
- display = (cp ? cp.display : true)
- }
- if (display) { %>
- <tr class="prop">
- <td valign="top" class="name">
- <label for="${p.name}"><g:message code="${domainClass.propertyName}.${p.name}.label" default="${p.naturalName}" /></label>
- </td>
- <td valign="top" class="value \${hasErrors(bean: ${propertyName}, field: '${p.name}', 'errors')}">
- ${renderEditor(p)}
- </td>
- </tr>
- <% } } } %>
- </tbody>
- </table>
- </div>
- <div class="buttons">
- <span class="button"><g:submitButton name="create" class="save" value="\${message(code: 'default.button.create.label', default: 'Create')}" /></span>
- </div>
- </g:form>
- </div>
- </body>
-</html>
View
64 src/templates/scaffolding/edit.gsp
@@ -1,64 +0,0 @@
-<% import grails.persistence.Event %>
-<% import org.codehaus.groovy.grails.plugins.PluginManagerHolder %>
-<%=packageName%>
-<html>
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
- <meta name="layout" content="main" />
- <g:set var="entityName" value="\${message(code: '${domainClass.propertyName}.label', default: '${className}')}" />
- <title><g:message code="default.edit.label" args="[entityName]" /></title>
- </head>
- <body>
- <div class="nav">
- <span class="menuButton"><a class="home" href="\${createLink(uri: '/')}"><g:message code="default.home.label"/></a></span>
- <span class="menuButton"><g:link class="list" action="list"><g:message code="default.list.label" args="[entityName]" /></g:link></span>
- <span class="menuButton"><g:link class="create" action="create"><g:message code="default.new.label" args="[entityName]" /></g:link></span>
- </div>
- <div class="body">
- <h1><g:message code="default.edit.label" args="[entityName]" /></h1>
- <g:if test="\${flash.message}">
- <div class="message">\${flash.message}</div>
- </g:if>
- <g:hasErrors bean="\${${propertyName}}">
- <div class="errors">
- <g:renderErrors bean="\${${propertyName}}" as="list" />
- </div>
- </g:hasErrors>
- <g:form method="post" <%= multiPart ? ' enctype="multipart/form-data"' : '' %>>
- <g:hiddenField name="id" value="\${${propertyName}?.id}" />
- <g:hiddenField name="version" value="\${${propertyName}?.version}" />
- <div class="dialog">
- <table>
- <tbody>
- <% excludedProps = Event.allEvents.toList() << 'version' << 'id' << 'dateCreated' << 'lastUpdated'
- persistentPropNames = domainClass.persistentProperties*.name
- props = domainClass.properties.findAll { persistentPropNames.contains(it.name) && !excludedProps.contains(it.name) }
- Collections.sort(props, comparator.constructors[0].newInstance([domainClass] as Object[]))
- display = true
- boolean hasHibernate = PluginManagerHolder.pluginManager.hasGrailsPlugin('hibernate')
- props.each { p ->
- if (hasHibernate) {
- cp = domainClass.constrainedProperties[p.name]
- display = (cp?.display ?: true)
- }
- if (display) { %>
- <tr class="prop">
- <td valign="top" class="name">
- <label for="${p.name}"><g:message code="${domainClass.propertyName}.${p.name}.label" default="${p.naturalName}" /></label>
- </td>
- <td valign="top" class="value \${hasErrors(bean: ${propertyName}, field: '${p.name}', 'errors')}">
- ${renderEditor(p)}
- </td>
- </tr>
- <% } } %>
- </tbody>
- </table>
- </div>
- <div class="buttons">
- <span class="button"><g:actionSubmit class="save" action="update" value="\${message(code: 'default.button.update.label', default: 'Update')}" /></span>
- <span class="button"><g:actionSubmit class="delete" action="delete" value="\${message(code: 'default.button.delete.label', default: 'Delete')}" onclick="return confirm('\${message(code: 'default.button.delete.confirm.message', default: 'Are you sure?')}');" /></span>
- </div>
- </g:form>
- </div>
- </body>
-</html>
View
61 src/templates/scaffolding/list.gsp
@@ -1,61 +0,0 @@
-<% import grails.persistence.Event %>
-<%=packageName%>
-<html>
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
- <meta name="layout" content="main" />
- <g:set var="entityName" value="\${message(code: '${domainClass.propertyName}.label', default: '${className}')}" />
- <title><g:message code="default.list.label" args="[entityName]" /></title>
- </head>
- <body>
- <div class="nav">
- <span class="menuButton"><a class="home" href="\${createLink(uri: '/')}"><g:message code="default.home.label"/></a></span>
- <span class="menuButton"><g:link class="create" action="create"><g:message code="default.new.label" args="[entityName]" /></g:link></span>
- </div>
- <div class="body">
- <h1><g:message code="default.list.label" args="[entityName]" /></h1>
- <g:if test="\${flash.message}">
- <div class="message">\${flash.message}</div>
- </g:if>
- <div class="list">
- <table>
- <thead>
- <tr>
- <% excludedProps = Event.allEvents.toList() << 'version'
- allowedNames = domainClass.persistentProperties*.name << 'id' << 'dateCreated' << 'lastUpdated'
- props = domainClass.properties.findAll { allowedNames.contains(it.name) && !excludedProps.contains(it.name) && !Collection.isAssignableFrom(it.type) }
- Collections.sort(props, comparator.constructors[0].newInstance([domainClass] as Object[]))
- props.eachWithIndex { p, i ->
- if (i < 6) {
- if (p.isAssociation()) { %>
- <th><g:message code="${domainClass.propertyName}.${p.name}.label" default="${p.naturalName}" /></th>
- <% } else { %>
- <g:sortableColumn property="${p.name}" title="\${message(code: '${domainClass.propertyName}.${p.name}.label', default: '${p.naturalName}')}" />
- <% } } } %>
- </tr>
- </thead>
- <tbody>
- <g:each in="\${${propertyName}List}" status="i" var="${propertyName}">
- <tr class="\${(i % 2) == 0 ? 'odd' : 'even'}">
- <% props.eachWithIndex { p, i ->
- if (i == 0) { %>
- <td><g:link action="show" id="\${${propertyName}.id}">\${fieldValue(bean: ${propertyName}, field: "${p.name}")}</g:link></td>
- <% } else if (i < 6) {
- if (p.type == Boolean.class || p.type == boolean.class) { %>
- <td><g:formatBoolean boolean="\${${propertyName}.${p.name}}" /></td>
- <% } else if (p.type == Date.class || p.type == java.sql.Date.class || p.type == java.sql.Time.class || p.type == Calendar.class) { %>
- <td><g:formatDate date="\${${propertyName}.${p.name}}" /></td>
- <% } else { %>
- <td>\${fieldValue(bean: ${propertyName}, field: "${p.name}")}</td>
- <% } } } %>
- </tr>
- </g:each>
- </tbody>
- </table>
- </div>
- <div class="paginateButtons">
- <g:paginate total="\${${propertyName}Total}" />
- </div>
- </div>
- </body>
-</html>
View
171 src/templates/scaffolding/renderEditor.template
@@ -1,171 +0,0 @@
-<% if (property.type == Boolean.class || property.type == boolean.class)
- out << renderBooleanEditor(domainClass, property)
- else if (Number.class.isAssignableFrom(property.type) || (property.type.isPrimitive() && property.type != boolean.class))
- out << renderNumberEditor(domainClass, property)
- else if (property.type == String.class)
- out << renderStringEditor(domainClass, property)
- else if (property.type == Date.class || property.type == java.sql.Date.class || property.type == java.sql.Time.class || property.type == Calendar.class)
- out << renderDateEditor(domainClass, property)
- else if (property.type == URL.class)
- out << renderStringEditor(domainClass, property)
- else if (property.isEnum())
- out << renderEnumEditor(domainClass, property)
- else if (property.type == TimeZone.class)
- out << renderSelectTypeEditor("timeZone", domainClass, property)
- else if (property.type == Locale.class)
- out << renderSelectTypeEditor("locale", domainClass, property)
- else if (property.type == Currency.class)
- out << renderSelectTypeEditor("currency", domainClass, property)
- else if (property.type==([] as Byte[]).class) //TODO: Bug in groovy means i have to do this :(
- out << renderByteArrayEditor(domainClass, property)
- else if (property.type==([] as byte[]).class) //TODO: Bug in groovy means i have to do this :(
- out << renderByteArrayEditor(domainClass, property)
- else if (property.manyToOne || property.oneToOne)
- out << renderManyToOne(domainClass, property)
- else if ((property.oneToMany && !property.bidirectional) || (property.manyToMany && property.isOwningSide()))
- out << renderManyToMany(domainClass, property)
- else if (property.oneToMany)
- out << renderOneToMany(domainClass, property)
-
- private renderEnumEditor(domainClass, property) {
- return "<g:select name=\"${property.name}\" from=\"\${${property.type.name}?.values()}\" keys=\"\${${property.type.name}?.values()*.name()}\" value=\"\${${domainInstance}?.${property.name}?.name()}\" ${renderNoSelection(property)} />"
- }
-
- private renderStringEditor(domainClass, property) {
- if (!cp) {
- return "<g:textField name=\"${property.name}\" value=\"\${${domainInstance}?.${property.name}}\" />"
- }
- else {
- if ("textarea" == cp.widget || (cp.maxSize > 250 && !cp.password && !cp.inList)) {
- return "<g:textArea name=\"${property.name}\" cols=\"40\" rows=\"5\" value=\"\${${domainInstance}?.${property.name}}\" />"
- }
- else {
- if (cp.inList) {
- return "<g:select name=\"${property.name}\" from=\"\${${domainInstance}.constraints.${property.name}.inList}\" value=\"\${${domainInstance}?.${property.name}}\" valueMessagePrefix=\"${domainClass.propertyName}.${property?.name}\" ${renderNoSelection(property)} />"
- }
- else {
- def sb = new StringBuffer("<g:")
- cp.password ? sb << "passwordField " : sb << "textField "
- sb << "name=\"${property.name}\" "
- if (cp.maxSize) sb << "maxlength=\"${cp.maxSize}\" "
- if (!cp.editable) sb << "readonly=\"readonly\" "
- sb << "value=\"\${${domainInstance}?.${property.name}}\" />"
- return sb.toString()
- }
- }
- }
- }
-
- private renderByteArrayEditor(domainClass, property) {
- return "<input type=\"file\" id=\"${property.name}\" name=\"${property.name}\" />"
- }
-
- private renderManyToOne(domainClass,property) {
- if (property.association) {
- return "<g:select name=\"${property.name}.id\" from=\"\${${property.type.name}.list()}\" optionKey=\"id\" value=\"\${${domainInstance}?.${property.name}?.id}\" ${renderNoSelection(property)} />"
- }
- }
-
- private renderManyToMany(domainClass, property) {
- return "<g:select name=\"${property.name}\" from=\"\${${property.referencedDomainClass.fullName}.list()}\" multiple=\"yes\" optionKey=\"id\" size=\"5\" value=\"\${${domainInstance}?.${property.name}*.id}\" />"
- }
-
- private renderOneToMany(domainClass, property) {
- def sw = new StringWriter()
- def pw = new PrintWriter(sw)
- pw.println()
- pw.println "<ul>"
- pw.println "<g:each in=\"\${${domainInstance}?.${property.name}?}\" var=\"${property.name[0]}\">"
- pw.println " <li><g:link controller=\"${property.referencedDomainClass.propertyName}\" action=\"show\" id=\"\${${property.name[0]}.id}\">\${${property.name[0]}?.encodeAsHTML()}</g:link></li>"
- pw.println "</g:each>"
- pw.println "</ul>"
- pw.println "<g:link controller=\"${property.referencedDomainClass.propertyName}\" action=\"create\" params=\"['${domainClass.propertyName}.id': ${domainInstance}?.id]\">\${message(code: 'default.add.label', args: [message(code: '${property.referencedDomainClass.propertyName}.label', default: '${property.referencedDomainClass.shortName}')])}</g:link>"
- return sw.toString()
- }
-
- private renderNumberEditor(domainClass, property) {
- if (!cp) {
- if (property.type == Byte.class) {
- return "<g:select name=\"${property.name}\" from=\"\${-128..127}\" value=\"\${fieldValue(bean: ${domainInstance}, field: '${property.name}')}\" />"
- }
- else {
- return "<g:textField name=\"${property.name}\" value=\"\${fieldValue(bean: ${domainInstance}, field: '${property.name}')}\" />"
- }
- }
- else {
- if (cp.range) {
- return "<g:select name=\"${property.name}\" from=\"\${${cp.range.from}..${cp.range.to}}\" value=\"\${fieldValue(bean: ${domainInstance}, field: '${property.name}')}\" ${renderNoSelection(property)} />"
- }
- else if (cp.inList) {
- return "<g:select name=\"${property.name}\" from=\"\${${domainInstance}.constraints.${property.name}.inList}\" value=\"\${fieldValue(bean: ${domainInstance}, field: '${property.name}')}\" valueMessagePrefix=\"${domainClass.propertyName}.${property?.name}\" ${renderNoSelection(property)} />"
- }
- else {
- return "<g:textField name=\"${property.name}\" value=\"\${fieldValue(bean: ${domainInstance}, field: '${property.name}')}\" />"
- }
- }
- }
-
- private renderBooleanEditor(domainClass, property) {
- if (!cp) {
- return "<g:checkBox name=\"${property.name}\" value=\"\${${domainInstance}?.${property.name}}\" />"
- }
- else {
- def sb = new StringBuffer("<g:checkBox name=\"${property.name}\" ")
- if (cp.widget) sb << "widget=\"${cp.widget}\" ";
- cp.attributes.each { k, v ->
- sb << "${k}=\"${v}\" "
- }
- sb << "value=\"\${${domainInstance}?.${property.name}}\" />"
- return sb.toString()
- }
- }
-
- private renderDateEditor(domainClass, property) {
- def precision = (property.type == Date.class || property.type == java.sql.Date.class || property.type == Calendar.class) ? "day" : "minute";
- if (!cp) {
- return "<g:datePicker name=\"${property.name}\" precision=\"${precision}\" value=\"\${${domainInstance}?.${property.name}}\" />"
- }
- else {
- if (!cp.editable) {
- return "\${${domainInstance}?.${property.name}?.toString()}"
- }
- else {
- def sb = new StringBuffer("<g:datePicker name=\"${property.name}\" ")
- if (cp.format) sb << "format=\"${cp.format}\" "
- if (cp.widget) sb << "widget=\"${cp.widget}\" "
- cp.attributes.each { k, v ->
- sb << "${k}=\"${v}\" "
- }
- sb << "precision=\"${precision}\" value=\"\${${domainInstance}?.${property.name}}\" ${renderNoSelection(property)} />"
- return sb.toString()
- }
- }
- }
-
- private renderSelectTypeEditor(type, domainClass,property) {
- if (!cp) {
- return "<g:${type}Select name=\"${property.name}\" value=\"\${${domainInstance}?.${property.name}}\" />"
- }
- else {
- def sb = new StringBuffer("<g:${type}Select name=\"${property.name}\" ")
- if (cp.widget) sb << "widget=\"${cp.widget}\" ";
- cp.attributes.each { k, v ->
- sb << "${k}=\"${v}\" "
- }
- sb << "value=\"\${${domainInstance}?.${property.name}}\" ${renderNoSelection(property)} />"
- return sb.toString()
- }
- }
-
- private renderNoSelection(property) {
- if (property.optional) {
- if (property.manyToOne || property.oneToOne) {
- return "noSelection=\"['null': '']\""
- }
- else {
- return "noSelection=\"['': '']\""
- }
- }
- return ""
- }
-%>
View
64 src/templates/scaffolding/show.gsp
@@ -1,64 +0,0 @@
-<% import grails.persistence.Event %>
-<%=packageName%>
-<html>
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
- <meta name="layout" content="main" />
- <g:set var="entityName" value="\${message(code: '${domainClass.propertyName}.label', default: '${className}')}" />
- <title><g:message code="default.show.label" args="[entityName]" /></title>
- </head>
- <body>
- <div class="nav">
- <span class="menuButton"><a class="home" href="\${createLink(uri: '/')}"><g:message code="default.home.label"/></a></span>
- <span class="menuButton"><g:link class="list" action="list"><g:message code="default.list.label" args="[entityName]" /></g:link></span>
- <span class="menuButton"><g:link class="create" action="create"><g:message code="default.new.label" args="[entityName]" /></g:link></span>
- </div>
- <div class="body">
- <h1><g:message code="default.show.label" args="[entityName]" /></h1>
- <g:if test="\${flash.message}">
- <div class="message">\${flash.message}</div>
- </g:if>
- <div class="dialog">
- <table>
- <tbody>
- <% excludedProps = Event.allEvents.toList() << 'version'
- allowedNames = domainClass.persistentProperties*.name << 'id' << 'dateCreated' << 'lastUpdated'
- props = domainClass.properties.findAll { allowedNames.contains(it.name) && !excludedProps.contains(it.name) }
- Collections.sort(props, comparator.constructors[0].newInstance([domainClass] as Object[]))
- props.each { p -> %>
- <tr class="prop">
- <td valign="top" class="name"><g:message code="${domainClass.propertyName}.${p.name}.label" default="${p.naturalName}" /></td>
- <% if (p.isEnum()) { %>
- <td valign="top" class="value">\${${propertyName}?.${p.name}?.encodeAsHTML()}</td>
- <% } else if (p.oneToMany || p.manyToMany) { %>
- <td valign="top" style="text-align: left;" class="value">
- <ul>
- <g:each in="\${${propertyName}.${p.name}}" var="${p.name[0]}">
- <li><g:link controller="${p.referencedDomainClass?.propertyName}" action="show" id="\${${p.name[0]}.id}">\${${p.name[0]}?.encodeAsHTML()}</g:link></li>
- </g:each>
- </ul>
- </td>
- <% } else if (p.manyToOne || p.oneToOne) { %>
- <td valign="top" class="value"><g:link controller="${p.referencedDomainClass?.propertyName}" action="show" id="\${${propertyName}?.${p.name}?.id}">\${${propertyName}?.${p.name}?.encodeAsHTML()}</g:link></td>
- <% } else if (p.type == Boolean.class || p.type == boolean.class) { %>
- <td valign="top" class="value"><g:formatBoolean boolean="\${${propertyName}?.${p.name}}" /></td>
- <% } else if (p.type == Date.class || p.type == java.sql.Date.class || p.type == java.sql.Time.class || p.type == Calendar.class) { %>
- <td valign="top" class="value"><g:formatDate date="\${${propertyName}?.${p.name}}" /></td>
- <% } else if(!p.type.isArray()) { %>
- <td valign="top" class="value">\${fieldValue(bean: ${propertyName}, field: "${p.name}")}</td>
- <% } %>
- </tr>
- <% } %>
- </tbody>
- </table>
- </div>
- <div class="buttons">
- <g:form>
- <g:hiddenField name="id" value="\${${propertyName}?.id}" />
- <span class="button"><g:actionSubmit class="edit" action="edit" value="\${message(code: 'default.button.edit.label', default: 'Edit')}" /></span>
- <span class="button"><g:actionSubmit class="delete" action="delete" value="\${message(code: 'default.button.delete.label', default: 'Delete')}" onclick="return confirm('\${message(code: 'default.button.delete.confirm.message', default: 'Are you sure?')}');" /></span>
- </g:form>
- </div>
- </div>
- </body>
-</html>
View
17 test/integration/org/grails/jquery/validation/ui/ConstraintsRetrieveTests.groovy
@@ -4,6 +4,7 @@ import grails.test.*
import grails.util.GrailsNameUtils
import org.springframework.validation.BeanPropertyBindingResult
import org.springframework.util.ReflectionUtils
+import org.springframework.validation.DefaultMessageCodesResolver
class ConstraintsRetrieveTests extends GrailsUnitTestCase {
def grailsApplication
@@ -85,6 +86,22 @@ class ConstraintsRetrieveTests extends GrailsUnitTestCase {
assertNotNull commandClass.constraints
}
+ void testRetrieveMessageCodesFromPersonWorkAddressNumber() {
+ def domainClass = grailsApplication.classLoader.loadClass("org.grails.jquery.validation.ui.Person")
+ def constrainedProperties = getConstrainedProperties(domainClass)
+
+ constrainedProperties.each { name, constrainedProperty ->
+ if (!constrainedProperty.appliedConstraints) {
+ println "Property '$name' has no constraints"
+ }
+ else {
+ constrainedProperty.appliedConstraints.each { c ->
+ println "Property '$name' has constraint $c"
+ }
+ }
+ }
+ }
+
// http://www.ibm.com/developerworks/java/library/j-grails10148/index.html
private hasError(validatableClass, property, constraint, errors) {
def badField = errors.getFieldError(property)
Please sign in to comment.
Something went wrong with that request. Please try again.