This page last changed on Feb 27, 2006 by [email protected].

Scaffolding

What is Scaffolding?

Scaffolding allows you to auto-generate a whole application for a given domain class including:

  • The necessary views
  • Controller actions for create/read/update/delete (CRUD) operations

Enabling Scaffolding

The simplist way to get started with scaffolding is to enable scaffolding via the "scaffold" property. For the "Book" domain class, you need to set the "scaffold" property on a controller to true:

class BookController {
   @Property scaffold = true
}

The above works because the "BookController" follows the same naming convention as the "Book" domain class, if we wanted to scaffold a specific domain class you can reference the class directly in the scaffold property:

@Property scaffold = Author.class

And thats it! If you run this grails application the necessary actions and views will be auto-generated at runtime. The following actions are dynamically implemented by default by the runtime scaffolding mechanism:

  • list
  • show
  • edit
  • delete
  • create
  • save
  • update

An interface like the one demonstrated in the screenshots below will be generated automatically:

If you prefer to keep your domain model in Java and mapped with Hibernate you can still use scaffolding, simply import the necessary class and set the scaffold property to it.

Dynamic Scaffolding

Because Grails does not use code templates to achieve this you can add your own actions to the scaffolded controller that interact with the scaffolded actions:

class BookController {
   @Property scaffold = Book.class

   @Property changeAuthor = {
        def b = Book.get( params["id"] )
        b.author = Auhtor.get( params["author.id"] )
        b.save()

        // redirect to a scaffolded action
        redirect(action:show)
   }
}

You can also override the scaffolded actions with your own actions if necessary:

class BookController {
   @Property scaffold = Book.class

   // over rides scaffolded action to return both authors and books
   @Property list = {
         [ "books" : Book.list(), "authors": Author.list() ]
   }
}

 

Generating Controllers & Views

The above scaffolding features are useful but in real world situations its likely that you will want to customise the logic and views. Grails allows you to generate a controller and the views used to create the above interface via the command line. To generated a controller type:

grails generate-controller

Or to generate the views type:

grails generate-views

Or to generate everything type:

grails generate-all

All these commands will prompt you for the name of the domain class to generate to various artifacts for the specified domain class. You can even generate a controller and views for a domain class that is written in Java and mapped with Hibernate!

Customising the Generated views

The views that Grails generates have some form of intelligence in that they adapt to the Validation constraints. For example you can change the order that fields appear in the views simply by re-ordering the constraints in the builder:

@Property constraints = {
      title()
      releaseDate()
}

You can also get the generator to generate lists instead of text inputs if you use the "inList" constraint:

@Property constraints = {
      title()
      category(inList:["Fiction", "Non-fiction", "Biography"])
      releaseDate()
}

Or if you use the range constraint on a number:

@Property constraints = {
        age(range:18..65)
}

Restricting the length via a constraint also effects how many characters can be entered in the generated view:

@Property constraints = {
        name(length:0..30)
}

And you can change an input field to be a text area by using the "widget" constraint:

@Property constraints = {
        description(widget:'textarea')
}

Java Integration

If your domain model is written in Java and mapped with Hibernate you can still take advantage of Grails' scaffolding mechanism. For the purpose of this documentation it is assumed you have read how Grails' Hibernate integration works in the section on GORM, needless to say to scaffold a hibernate domain class simply reference the domain class in the controller:

import com.books.HibernateBook
class BookController {
     @Property scaffold = HibernateBook.class
}

If you want to generate the controller and views for a Hibernate domain class you can still do so, but make sure you type the full package and class name.

To integrate with the Grails constraints mechanism and hence hook into useful things like the way the views are generated and Grails' Validation mechanism you can do so by writing a method that returns the constraints using the "org.codehaus.groovy.grails.orm.hibernate.validation.ConstrainedPersistentProperty" class, note that the example below uses Hibernate annotations' "Transient" annotation to tell Hibernate that it is not a persistent property:

@Transient
   public Map getConstraints() {
       ConstrainedProperty titleConstraint = new
ConstrainedPersistentProperty(getClass(), "title", String.class );
       titleConstraint.setOrder(1);
       titleConstraint.setLength(new IntRange(5,15));
       ConstrainedProperty descConstraint = new
ConstrainedPersistentProperty(getClass(), "title", String.class );
       descConstraint.setOrder(2);
       descConstraint.setWidget("textarea");


       List constraints = new ArrayList();
       constraints.add(titleConstraint);
       constraints.add(descConstraint);

       return constraints;
   }

The code above is equivalent to the following Grails constraint with the builder syntax:

@Property constraints = {
    title(length:5..15)
    description(widget:'textarea')
}

grails_s1.jpg (image/jpeg)
grails_s2.jpg (image/jpeg)
grails_s3.jpg (image/jpeg)
grails_s4.jpg (image/jpeg)
Document generated by Confluence on Mar 29, 2006 08:46