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:
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:
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: