How to add a simple search form

Grails comes with a great scaffolding feature that let you build CRUD functionalities for your domain classes. In this tutorial, I’ll show you how to add basic searching capability to a scaffolded controller.

First, let’s build a simple Todo application:

grails create-app todo
cd todo
grails create-domain-class Task
grails create-controller Task

Now, let’s add an attribute to our Task class:

package todo

class Task {

    String description

}

Then, enable dynamic scaffolding with the scaffold property:

package todo

class TaskController {

    static scaffold = true

}

That’s all it takes for Grails to build an application that let you list, show, edit or delete tasks.

Let’s test it by running the application:

grails run-app

To access your application, open http://localhost:8080/todo/task in a browser.

Here is what you see after entering a couple of tasks:

Scaffolded Todo application

Since we want to add searching capability to our application, we need to add a search form on our list page. First, we need to generate the current scaffolded views for our Task class with the following command:

grails generate-views todo.Task

This will create a task folder under grails-app/views and fill it with the scaffolding views. You can now open the list.gsp in order to customize the list view.

Let’s add a search form after the flash message:

// more code</pre>
<g:if test="${flash.message}">
<div class="message" role="status">${flash.message}</div>
</g:if>
<fieldset class="form">
	<g:form action="list" method="GET">
		<div class="fieldcontain">
			<label for="query">Search for tasks:</label>
			<g:textField name="query" value="${params.query}"/>
		</div>
	</g:form>
</fieldset>
<table>
// more code

We added an HTML form with an input text field named query. When the user enter something in this field and hit the enter key, the form submit a GET request to the list action of the TaskController.

But if you re-run the application and try to enter a search term, the application still lists all the tasks. It’s normal since we haven’t changed the behavior of the TaskController yet.

In order to customize the TaskController, we also need to generate a static scaffolded controller. So let’s do that with the following command:

grails generate-controller todo.Task

Grails will ask you to confirm if you want to override the current controller. Answer yes.

Now open the TaskController and delete everything except for the list method (and don’t forget to re-add the scaffold property):

package todo

class TaskController {

    static scaffold = true

    def list() {
        params.max = Math.min(params.max ? params.int('max') : 10, 100)
        [taskInstanceList: Task.list(params), taskInstanceTotal: Task.count()]
    }

}

Instead of returning all the tasks, let’s create an Hibernate criteria that looks for tasks that match the query string in the task description:

package todo

class TaskController {

    static scaffold = true

    def list() {
        params.max = Math.min(params.max ? params.int('max') : 5, 100)

        def taskList = Task.createCriteria().list (params) {
            if ( params.query ) {
                ilike("description", "%${params.query}%")
            }
        }

        [taskInstanceList: taskList, taskInstanceTotal: taskList.totalCount]
    }

}

If no query string is submitted, this code create an empty Hibernate criteria, which defaults back to the initial Task.list(params). Otherwise, it builds a criteria that looks for tasks with a description matching the query string (ilike is a case insensitive equivalent to a SQL like expression).

Note that passing the params map to the list method of the criteria enables pagination.

Now, re-run your application and try to enter a query string. It works!

Scaffolded application with search form

That’s how easy it is to add basic searching capability to a scaffolded application. 🙂

 

Advertisements