In my first post I'll show you how to create a simple application in Grails that uses jQuery UI autocomplete and AJAX.
- Project setup
- Building Application:
- creating domain class
- creating controller
- adding data via Bootstrap.groovy
- creating view
- modifying resource configuration
- creating javascript file
Project setup
-
Create a new project - I called it GrailsAutocomplete
Building Application
Creating domain class
- create com.example.Country domain class
package com.example
class Country {
String name
static constraints = {
name(blank: false, unique: true)
}
}
Creating controller
- create com.example.Country controller
package com.example
import grails.converters.JSON
class CountryController {
def scaffold = true
def index() {
redirect action: "autocomplete", params: params
}
def autocomplete() {
params.max = Math.min(params.max ? params.int('max') : 10, 100)
[countryInstanceList: Country.list(params), countryInstanceTotal: Country.count()]
}
def getAllCountries() {
def countries = Country.list()
def response = []
countries.each {
response << "${it.name}"
}
render response as JSON
}
}
- the index() method will redirect us to the autocomplete method
- the autocomplete() method will get all the country instance saved in the DB and pass them as a list
- by convention Grails will match the name of a method to a view with the same name; in a bit we will create our views/country/autocomplete.gsp
- the getAllCountries() method retrieves a list of all countries from DB
- we use each closure to populate the response list with the names of each Country instance
- our return value is the response rendered as JSON
- of course we don't have any country stored in the DB
Adding dummy data
- conf/BootStrap.groovy is a good place where we can add some countries to our DB
import com.example.Country
class BootStrap {
def init = { servletContext ->
def poland = new Country(name: "Poland");
poland.save(failOnError: true);
def holland = new Country(name: "Holland");
holland.save(failOnError: true);
def uk = new Country(name: "United Kingdom");
uk.save(failOnError: true);
def uae = new Country(name: "United Arab Emirates");
uae.save(failOnError: true);
def honduras = new Country(name: "Honduras");
honduras.save(failOnError: true);
}
def destroy = {
}
}
Creating view
- we can create now our views/country/autocomplete.gsp
<%@ page import="com.example.Country" %>
<!doctype html>
<html>
<head>
<meta name="layout" content="main">
<g:set var="entityName" value="${message(code: 'country.label', default: 'Country')}" />
<title><g:message code="default.list.label" args="[entityName]" /></title>
<r:require module="jquery-ui"/>
<g:javascript library="util"/>
</head>
<body>
<a href="#list-country" class="skip" tabindex="-1"><g:message code="default.link.skip.label" default="Skip to content…"/></a>
<div class="nav" role="navigation">
<ul>
<li><a class="home" href="${createLink(uri: '/')}"><g:message code="default.home.label"/></a></li>
<li><g:link class="create" action="create"><g:message code="default.new.label" args="[entityName]" /></g:link></li>
</ul>
</div>
<div id="list-country" class="content scaffold-list" role="main">
<div>
<h1 style="float: left;"><g:message code="default.list.label" args="[entityName]" /></h1><br/>
<input style="float: right; margin: 0px 10px 10px 0px;" type="text" name="country" id="country_textField" value="" placeholder="Enter country..."/>
</div>
<g:if test="${flash.message}">
<div class="message" role="status">${flash.message}</div>
</g:if>
<table>
<thead>
<tr>
<g:sortableColumn property="name" title="${message(code: 'country.name.label', default: 'Name')}" />
</tr>
</thead>
<tbody>
<g:each in="${countryInstanceList}" status="i" var="countryInstance">
<tr class="${(i % 2) == 0 ? 'even' : 'odd'}">
<td><g:link action="show" id="${countryInstance.id}">${fieldValue(bean: countryInstance, field: "name")}</g:link></td>
</tr>
</g:each>
</tbody>
</table>
<div class="pagination">
<g:paginate total="${countryInstanceTotal}" />
</div>
</div>
</body>
</html>
- inside the head tag we have two important lines:
<r:require module="jquery-ui"/>
<g:javascript library="util"/>
- r:require uses Grails resource plugin that will allow us to use jQuery UI on this page
- g:javascript will import JS file called util
- we have to tell Grails where to look for this file
Modifying resource configuration
- go to conf/ApplicationResource.groovy and add reference to util resource
- modules = {
application {
resource url:'js/application.js'
}
util {
resource url:'js/util.js'
}
}
Creating javascript file
- now we can create a util.js file in web-app/js folder
$(document).ready(function() {
$.ajax({
type: "GET",
url: "/GrailsAutocomplete/country/getAllCountries",
success : function(response) {
$("#country_textField").autocomplete({
source: response
});
}
});
});
- we do an AJAX request to /GrailsAutocomplete/country/getAllCountries once we finish loading the html for the page
- this URL will map to our Country controller and to it's method getAllCountries() that returns a JSON file with the names of the countries that are stored in the DB
- we use this JSON to populate our autocomplete
- note that the $(#country_textField) matches the id of our input from autocomplete.gsp
Running the app
Now we can run our app and go to:
http://localhost:8080/GrailsAutocomplete/country/
- we should see a list of countries and an input box on the right-hand side
- when you start typing 'ola' the list should be populated with 'Holand' and 'Poland'