Showing posts with label scaffolding. Show all posts
Showing posts with label scaffolding. Show all posts

Thursday, July 15, 2010

just some notes about working with scaffolding code

When I modify scaffolding templates I always wonder how to obtain different properties like e.g. the class name or the id of the current instance. A general remark: What confused me most in the beginning was notation like \${${...}}. What you have to know is that \$ is escaped and is therefore what you can normally achieve in GSPs with a $. The unescaped $ within that clause is for the template. When actual code is generated from the template those $ are resolved immediately. You can therefore only use properties that are kown at this stage. Here are a few examples.

\${${className}}
This resolves the long version of the current class name

You often see that properties of an instance are iterated. The variable name of a property is then 'p':

${p.name}
This is the name of the property as it is used in the current instance. You need this value if you want to access that property in a controller (similar to this: domainClassInstance."${params.propertyName}").

${p.referencedDomainClass?.propertyName}
This one gives you the propertyName of the referenced domain class, thus the domain class of the property p. The propertyName is equal to the controller name if you stick to the convention.

${p.referencedDomainClass?.fullName}
Sometimes you need to have the full class name with the whole package notation. This can be useful for domain class instantiation (see my last post).

${p.referencedDomainClass?.shortName}
This is the actual class name omitting the package notation.

Monday, May 31, 2010

in-line editing in scaffolded show.gsp

In the default pages created by the scaffolding mechanism of grails, it is quite cumbersome that whenever you want to change a value of a domain class you have to go to the edit page and afterwards back to the show page. Two complete site loads that do not fit into the web 2.0 paradigm.

Usually one would apply in-line editing to bring in a cool and useful AJAX feature and in fact every JS library seems to have built-in support. It is however quite labourous if you have to add this feature manually to every field even if you make things easier with a tag lib as suggested in the book "Beginning Groovy and Grails" by Christopher M. Judd, Joseph Faisal Nusairat and James Shingler.

I thought about the problem and then decided to try to combine scaffolding with this technique. I used the example from the book as a guideline.

I changed the following entry within show.gsp:

<td valign="top" class="value">\${fieldValue(bean: ${propertyName}, field: "${p.name}")}</td>

to:
<td>
 <g:editInPlace 
  id="${p.name}"       
  url="[action: 'editField', id:${propertyName}.id]"
  rows="1"
  cols="10"
  paramName="${p.name}">\${fieldValue(bean: ${propertyName}, field: "${p.name}")}
 </g:editInPlace>
</td>

One can use the TagLib given by the book, but you have to modify the action in order to work with arbitrary fields. Add the following method to the scaffolded Controller.groovy (/src/templates/scaffolding):

def editField = {
  // Retrieve member
  def ${propertyName} = ${className}.get(params.id)
  if(${propertyName})
      {
      ${propertyName}.properties = params
      ${propertyName}.save()
      // Render a new page.
      render params.get(params.editorId)
  }
    }

Tuesday, May 4, 2010

service dependency injection does not work in scaffolded controllers

When I wanted to access user information in the scaffolding code of the controller (/src/scaffolding/Controller.groovy) my first guess was to define the authenticateService and let dependency injection do the trick. Unfortunately, this approach did not work.

def authenticateService is never injected and therfore a useless null object.

I spent some time on google and it turned out that this is an open issue and that others had stumbled about the same problem. I was happy to see that someone had found a workaround:

def authenticateService = org.codehaus.groovy.grails.commons.ApplicationHolder.application.mainContext.getBean("authenticateService")


Using this approach arbitrary services can be injected into the scaffolded controllers.