With the announcement of an alpha release of jQuery Mobile, I decided to check it out and see how easy it would be to develop a web application that is optimized for mobile/tablet devices.
If you head over to the documentation site, the first thing you will notice is that the docs are actually built using jQuery mobile, which is quite cool since it gives you a quick feel of what to expect from the library. After skimming through the docs and building some sample pages, here are some of the things that I really liked about it (along with the other advertised features of course)
- Markup driven (you can build a compile mobile web app with no javascript code at all)
- Theming capability
- Cool looking list views
After realizing how easy it is to prototype a mobile web app with jQuery mobile and how cool the rendered pages look out of the box, a crazy voice started whispering in my head (it was mainly asking a question really…), “How cool would it be to prototype mobile web apps using grails’s scaffolding?”
And my answer was “Wayyy Cool”, which is why I started my terminal and created a new grails application to see how I can achieve this.
Okay, so I knew in order to change the default scaffolded views generated by grails I needed to first install the templates (which are not found by default when creating an application). If you have run into a situation requiring you to edit the web.xml file you have probably done this step before (installing the templates). So within my newly created grails application I issued the following command
grails install-templates
This will create a number of files in your application’s src/templates folder including the ones responsible for populating your grails artifacts when issuing commands like grails create-controller etc… as well the templates responsible for scaffolding, which is what interests me for this example.
You will find that within the src/templates/scaffolding directory there are files conveniently named according to the view file names you get when you generate views using the grails generate-views command, you will also find a Controller.groovy which is responsible for generating controllers with the grails generate-controller command , and a file called renderEditor.template which is responsible for rendering the different form elements in the create and edit pages.
So for the purpose of my test, I will be editing list.gsp, show.gsp, create.gsp and edit.gsp and changing them to generate jQuery mobile markup. Also before I edit those file I will clean up the main template (main.gsp in grails-app/views/layout) to include the jQuery mobile css and javascript files to be used in all pages.
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="${resource(dir:'css',file:'jquery.mobile-1.0a1.min.css')}"/>
<link rel="stylesheet" href="${resource(dir:'css',file:'main.css')}" type="text/css" media="all"/>
<script src="${resource(dir:'js',file:'jquery-1.4.3.min.js')}" /></script>
<script src="${resource(dir:'js',file:'jquery.mobile-1.0a1.min.js')}"></script>
<title><g:layoutTitle default="Grails" /></title>
<g:layoutHead />
</head>
<body>
<g:layoutBody />
</body>
</html>
Now that I have the required javascript and css, I will start by showing a sample of the edits I made for the list.gsp template, you can check out the rest of the files I’ve edited from the attached sample source code (at the bottom of the page).
jQuery mobile page basics
According to the docs, a jQuery mobile page with a header, content and footer will typically look something like this (inside the main body tag)
<div data-role="page"> <div data-role="header">...</div> <div data-role="content">...</div> <div data-role="footer">...</div> </div>
You will notice the use the attribute data-role to indicate the role of each div. There are other attributes used by jQuery mobile which will control themes, icons and their locations, button grouping etc… which I will run into later on.
Having defined the skeleton of each page, the first and simplest page template to edit is the list.gsp
Mobil-izing the list template
I want my list page to have the following attributes
- A Header showing
- Title of the domain class list being shown
- Button to take me back to the home (index) page
- The content will list the domain classes in my db showing the toString() representation of the domain object (to keep things simple I will not show a table like the default behavior, also it looks way cooler this way)
- A footer showing
- A button to create a new instance of the domain
- Pagination buttons
Here is how the list template is broken up after I’ve edited it (all the divs below are part of the parent div with data-role=”page”)
Header
<div data-role="header" data-nobackbtn="true" data-position="fixed">
<a href="\${createLink(uri: '/')}" data-icon="arrow-l">
<g:message code="default.nav.home.label" default="Home" />
</a>
<h1><g:message code="default.list.label" args="[entityName]" /></h1>
</div>
One important thing to note here, is that jQuery mobile can automatically add back button support to your application’s headers which is quite cool, but I preferred to add my own back buttons instead of the automatically created ones, hence you can see the data-nobackbtn=”true” attribute instructing the framework not to add the button for me, also I’ve added the attribute data-position=”fixed” which makes my header follow and stay at the top of the page when I scroll down a long page. (The current behavior is a bit buggy, but it looks like it is being worked on), the rest should be clear if you’ve written any gsp code before.
Content
<div data-role="content">
<g:if test="\${flash.message}">
<div class="message"><p>\${flash.message}</p></div>
</g:if>
<ul data-role="listview" >
<g:each in="\${${propertyName}List}" status="i" var="${propertyName}">
<li>
<g:link action="show" id="\${${propertyName}.id}">\${${propertyName}}</g:link>
</li>
</g:each>
</ul>
</div>
The content will first show any message that is in the flash scope (like the ones you get after deleting an object for example), below that is an unordered list which has the data-role=”listview” attribute which instructs the framework to create a, well…, ListView
Within the list view I just use the domain’s id to link to the show page, and depend on the toString() implementation on the domain class in order to render the the text that will displayed for each list item.
Footer
<div data-role="footer" data-position="fixed">
<g:set var="offInt" value="\${params.offset == null?0:params.offset.toInteger()}" />
<g:set var="offNext" value="\${offInt + params.max}" />
<g:set var="offPrev" value="\${((offInt - params.max)<0)?0:(offInt - params.max)}" />
<div data-role="controlgroup" data-type="horizontal">
<g:link action="create" data-icon="plus" data-theme="b">
<g:message code="default.button.add.label" default="Add" />
</g:link>
<g:if test="\${offInt > 0}">
<g:link action="list" params='[offset:"\${offPrev}"]' data-icon="arrow-l">
<g:message code="default.nav.previous.label" default="Previous" />
</g:link>
</g:if>
<g:if test="\${(${propertyName}List.size() < ${propertyName}Total) &&
(offNext < ${propertyName}Total)}">
<g:link action="list" params='[offset:"\${offNext}"]'
data-icon="arrow-r" data-iconpos='right' class="ui-btn-right">
<g:message code="default.nav.next.label" default="Next" />
</g:link>
</g:if>
</div>
</div>
Similar to the header, I’ve set the footer to follow the page scroll and always be displayed at the bottom by defining the data-position=”fixed” attribute. Within the footer you will find my humble attempt at a simplistic paging code which is probably buggy, but it worked fine with my tests, and is uncluttered enough for the purpose of showing in this article. Another thing which is cool is the data-role=”controlgroup” div, which will group buttons/links inside it into a grouped set of buttons which look really cool. You will also notice that I’ve added icons (which are part of the default themes) using the data-icon attribute, and changed the theme using the data-theme attribute.
Creating the application
Following similar steps I edited (mobil-ized) the show, create and edit templates so that I can scaffold all the views for my test application.
Next a created two simple domain classes, an Account domain with a one to many relationship to a Transaction domain something like this.
class Account {
String name
String description
List transactions = new ArrayList()
static hasMany = [transactions:Transaction]
static mapping = {
transactions(sort:"txnDate", order:"desc",cascade:"all-delete-orphan")
}
String toString(){
"${name}"
}
}
class Transaction {
double amount
String category
String comment
Date txnDate
Account account
static belongsTo = [account:Account]
String toString(){
"${comment} (\$${amount})"
}
}
Then all I had to do is grails generate-all for both domain classes, and I was left with a fully functional mobile web app that allows me to manage my expenses while on the go. Below are some images of how the app looks when run on an android emulator (you can also just fire it up in your browser).
Expenses App Home Page
Accounts List Page
Show Account Page
Add Transaction Page
In my examples, I have only touched the surface of what the framework has to offer though, by looking at the docs, you can take advantage of the new events that are available to create really cool stuff that are applicable for touch enabled devices, for example one cool thing that could be done is adding a tapHold event to the list items in the list page, which will popout a dialog asking whether you want to edit, delete or view this domain instance, similar to how native mobile applications do it.
Keep in mind that this is still an alpha release and it might have some missing features (e.g. some missing components like the data picker) and might still have some bugs, but I will be keeping an eye for jQuery mobile and will most likely use it once it is stable on a project that I am currently working on.
If you are interested, here is the full source for my sample application.





Excellent ! Are you planning to make a grails plugin with this base ? I’m the author of the grails iwebkit plugin and I was planning to also releasef a jquery mobile grails plugin.
Thanks, yea first thing that crossed my mind was that it would be nice to have it as a plugin. I did not look at the iwebkit plugin yet, but I will check it out and see how it works.
I haven’t delved into the realm of plugin development yet, but I guess this would make for a good exercise.
Well building a plugin is very easy, it’s building a regular grails app. With the code of your blog pot you have already 80% of the work done. You just have to write you plugin descriptor, maybe provide an extra script that will populate your custom templates (like ‘install-jquery-mobile-templates’) and also provide a taglib that encapsulates some css/html elements … Don’t hesitate if you have questions and we can co-author this plugin together if you want
Nice post with appropriate screenshots and code thanks for posting
It would be very nice to write it as a plugin. I can give you some help if you want.
Hi,
Thanks for the excellent tutorial.how can i give orientation changes to grails application.
Thanks & Regards,
Nithya
Did you guys do anything about the plugin? The article is awesome!
Haven’t worked on any sort of plugin for this tbh, but I got some emails with people who wanted to work on the plugin and use some of the stuff in the article. Not sure what happened there though.
Interesting post. One thought is that it seems like serving up the HTML UI via server-side (like Grails) over and over could easily eat up a lot of bandwidth on the client phone ($$ plus slow). Beware of that, and perhaps keep a caching system in mind!
This is a very helpful tutorial. I found it well written and very understandable. Thanks for the post I will be visiting your site in the future.
It works perfectly, but i have a trouble because the style css doesn’t work at first,
just when i refresh the page load.
Are there any good datepicker options for this? The default grails datepicker tag renders as three dropdowns (day, month, year), and jqm datepickers all want javascript methods for hiding/displaying/decoding the date.
Hello! I’m at work surfing around your blog from my new apple iphone! Just wanted to say I love reading through your blog and look forward to all your posts! Carry on the outstanding work!
If you desire to improve your experience only keep visiting this web page and be updated with the most recent news posted here.
I had been wondering if your web host is OK? Not that I am complaining, but sluggish loading instances times will sometimes affect your placement in google and can damage your high-quality score if advertising and marketing with Adwords.
Hi there this is somewhat of off topic but I was wanting to know if blogs use WYSIWYG editors or if
you have to manually code with HTML. I’m starting a blog soon but have no coding experience so I wanted to get advice from someone with experience. Any help would be greatly appreciated!