Grails 1.1 Web Application Development
上QQ阅读APP看书,第一时间看更新

Rendering a form

The first step to allow users to post messages is to present them with a form to enter the message data. To do this, you need to create a controller to handle the users request, and a view to show the form.

Message controller

Create a file called MessageController.groovy under the grails-app/controllers/app directory and place the following code in the new file:

package app
class MessageController {
def create = {
}
def save = {
}
}

Here you have created a controller for messages that can handle two actions: create and save. The following new URLs are now available in the application:

  • http://localhost:8080/teamwork/message/create
  • http://localhost:8080/teamwork/message/save

Of course, these URLs won't do anything yet as you have neither added any behavior to the controllers, nor created any views to render information to the user. The next step is to add the view for the Create Message page.

Groovy Server Pages

Groovy Server Pages (GSP) is the default view template language used when working with Grails. GSP provides a very similar syntax to JSP where you can use scriptlets or tags to perform logic within the pages. Like most features of Grails, there is a convention you must follow if you want to have the correct GSP used to render the result of an action.

Grails GSPs live under the grails-app/views directory. GSP files intended to render the results of an action on a particular controller should remain under a directory within views with the same name as the controller. So for MessageController, you will need to create the directory structure, grails-app/views/message.

The convention for finding a default view for an action is that Grails will look for a GSP under a directory matching the controller name and in a file matching the action name. In the case of the create action on MessageController, the default GSP page used for rendering would be grails-app/views/mesage/create.gsp.

Create message view

Create the GSP file views/mesage/create.gsp and add the following code:

<%@ page contentType="text/html;charset=UTF-8" %>
<html>
<head>
<meta http-equiv="Content-Type"
content="text/html; charset=UTF-8" />
<meta name="layout" content="main" /> 
<title>Post Message</title>
</head>
<body>
<p>Create a message form: coming soon!</p>
</body>
</html>

By creating this simple GSP, you should now be able to request the create action on MessageController and the GSP you have just created will be rendered. The line of markup highlighted above means that the GSP will be rendered with the main layout. You will learn more about the layouts in just a second, but first of all, fire up your application and check whether you can go to the URL http://localhost:8080/teamwork/message/create. You should see the window as shown in the following screenshot:

Create message view

Grails layouts

Grails uses SiteMesh (http://www.sitemesh.org) as its rendering engine. SiteMesh leverages layouts by allowing developers to decorate their pages with a consistent look and feel. Take another look at the GSP you have just created. The line you are interested in is highlighted:

<meta name="layout" content="main" />

This tells Grails to decorate the current page with the main layout. Layouts can be found under the grails-app/views/layouts directory. Look at the main.gsp file in this directory and you can see that it is referencing a stylesheet, setting up the basic page structure and loading the Grails logo. There are three tags being used that are of real interest, and should be defined in all layouts. These are: g:layoutTitle, g:layoutHead, and g:layoutBody.

Each of these tags is used to insert the contents of the page that is being rendered into the layout structure. For example, when the g:layoutTitle tag is called, the contents of the <title> element in the requested page will be rendered. The same applies to the g:layoutHead and the g:layoutBody tags.

Show the form

Now that you have a very simple view associated with the create message action, you can add some markup that will allow users to enter the details of a message. Modify message/create.gsp as shown here:

<%@ page contentType="text/html;charset=UTF-8" %>
<html>
<head>
<meta http-equiv="Content-Type"
content="text/html; charset=UTF-8"/>
<meta name="layout" content="main"/>
<title>Post Message</title>
</head>
<body>
<g:form action="save" class="inputform"> <fieldset> <dl> <dt>Title <span class="requiredfield">required</span> </dt> <dd><g:textField name="title" value="${message.title}" size="35" class="largeinput"/></dd> <dt>Message detail <span class="requiredfield">required</span> </dt> <dd><g:textArea name="detail" value="${message.detail}" cols="40" rows="10"/></dd> </dl> </fieldset> <g:submitButton name="Save" value="Save"/> | <g:link action="create">Cancel</g:link> </g:form> 
</body>
</html>

The markup above is very similar to plain HTML, with the exception of the Grails tags (with the g namespace). Grails tags are being used for the following:

  • Form
  • Input fields
  • Submit button
  • Cancel link

Grails, like many other web frameworks, provides tags to render forms and form elements, reducing the amount of HTML you need to write when creating forms.

In the g:form tag, you specify the Grails action ( save, in this case) to be executed when the form is submitted. If no controller is specified, then the current controller will be used. The Grails specific attributes for the g:form tag are:

  • controller — which controller to use when constructing the HTML action URL
  • action — which action to use when constructing the HTML action URL
  • id — which id to add when constructing the HTML action URL
  • url — a map containing the controller, action and id to use when constructing the URL

In addition to the above attributes, you can also specify any other attribute which will be passed through to the rendered HTML. This is particularly useful as it allows you to retain full control over the attributes that are defined by the HTML specification.

The use of the g:textField, g:textArea and g:submitButton tags are very similar and simply allow you to specify a name and a value for the form input. Again all the standard HTML attributes for these fields are rendered if you specify them.

Finally, you render a link that will clear any data entered in the form by reloading the Post Message page.

To add the required behavior for the Post Message page it is necessary to implement the create action in the MessageController class:

def create = {
return [ message: new Message() ]
}

The create action simply instantiates a new Message object and returns it in a model to be rendered. The model for rendering is constructed as an instance of Map, which contains the new Message object registered against the key 'message'. When you return a map from an action, the default view is still used for rendering. Additionally, each value in the map is made available to the GSP with the variable name matching its key. In the above example, create.gsp will receive a variable called 'message' that is assigned a new instance of the Message domain class.

Refresh the Post Message page in your browser, and you should see the form as shown in the following screenshot:

Show the form