Skip to main content

Resolving CSS Issues With Grails UI Plugin

I'm working on another Grails application and am using the fantastic Grails UI plugin for a lot of the UI controls. Grails UI is a really nice Grails-friendly wrapper around the YUI components and includes things like a dialog box, calendar controls, a rich text editor, and a whole lot more. This was my first real foray into using this plugin, so I started with a simple modal dialog box that would show the contact information details for people in a simple list.

The main point of this post is to outline the simple resolution to the CSS issues I was seeing because it took me a while to figure out what was going on, but I thought I'd outline some Grails and Grails UI magic along the way.

First, in order to use the Grails UI plugin you of course have to install it, which is as simple as:

grails install-plugin grails-ui

Next, on any view page on which you wish to use any Grails UI resources, you have to indicate which resources you're going to use on the page. The nice thing about this is it will only load the JavaScript for the specific UI resources you need on each page. In the case of this example I'm only using a dialog box, so I have this line in the head section of my view page:

<gui:resources components="dialog" />

Also in my head section I need to tell Grails I'll be using some AJAX on this page, so I use the javascript tag to load the Prototype library:

<g:javascript library="prototype" />

With Protoype loaded, pulling the contact details to be shown in the dialog box is dead simple using the Grails remoteLink tag:

<g:remoteLink controller="person"
               action="showDetail"
               id="${person.id}"
               update="personDiv"
               onComplete="showPersonDialog();">${person}</g:remoteLink>

If you're not familiar with Grails, what this does is tells Grails to make an AJAX call to the person controller, call the action showDetail, and pass the ID of the person object. We'll see what's returned by the AJAX call in a moment. The update attribute of the remoteLink tag tells Grails what DOM object to update with the results of the AJAX call, and the onComplete attribute indicates a JavaScript function to call when the AJAX call is complete.

If all I was doing was updating a DIV on the page I wouldn't need this, but since I need to show the Grails UI dialog box after I pull the contact details, I need a JavaScript function to handle that, so I added this to the head section of the view page:

<script type="text/javascript">
    function showPersonDialog() {
        GRAILSUI.personDialog.show();
    }
</script>

Next, let's check out the showDetail action in my Person controller to see what it's doing when the AJAX call is made:

def showDetail = {
    def personInstance = Person.get(params.id)
    if (!personInstance) {
        def message = "No person found with ID ${params.id}"
        render(view:"personDetail", model: [message : message])
    } else {
        render(view:"personDetail", model: [personInstance : personInstance])
    }
}

Here's the simple view that's rendered in the controller action above:

<g:if test="${message}">
    <p>${message}</p>
</g:if>

<g:if test="${personInstance}">
    <p>
        <strong>${personInstance.firstName} ${personInstance.lastName}</strong><br />
        ${personInstance.email}<br />
        Phone: ${personInstance.phone}<br />
        Cell: ${personInstance.cell}
    </p>
</g:if>

And finally, here's the code for the Grails UI dialog box and the DIV that is populated with the view above:

<div class="yui-skin-sam">
    <gui:dialog id="personDialog"
                width="400px"
                title="Contact Details"
                draggable="true"
                update="personDiv"
                modal="true">
        <div id="personDiv"></div>
    </gui:dialog>
</div>

This is all pretty straight-forward. What was happening, however, is when the dialog box was shown, there was no CSS being applied to it. The YUI components that are used by the Grails UI plugin have stylesheets associated with them, but when I checked the source code of the rendered page they seemed to be getting included just fine, and as you can see above I wrapped the dialog box in a div with the correct CSS class, which is yui-skin-sam.

At this point it's important to remember that when a Grails page is rendered it uses SiteMesh, which is basically a templating/page decoration framework. As many Grails applications do, I was using a main.gsp layout page, and each individual view page gets woven into this main template.

Therein lies the problem. As I said above this was simple enough in the end but since it took me a while to figure out I thought I'd share. Even though the YUI CSS was being included in the individual view page with the dialog box code on it, for some reason the CSS wasn't getting applied. I decided to experiment and put the yui-skin-sam class in the body tag in my main.gsp layout page, and this solved the problem.

In my case I didn't have any conflicting CSS involved so this solution didn't cause any issues, but if you have other CSS involved and applying a class to the body tag in the main layout page will cause issues, you can add the additional CSS references after the <g:layoutHead /> tag in the main layout page, and this will allow you to override any CSS that came earlier.

With all this in place the Grails UI components are being styled correctly and they're extremely nice additions to any Grails app.

Comments

Popular posts from this blog

Installing and Configuring NextPVR as a Replacement for Windows Media Center

If you follow me on Google+ you'll know I had a recent rant about Windows Media Center, which after running fine for about a year suddenly decided as of January 29 it was done downloading the program guide and by extension was therefore done recording any TV shows.

I'll spare you more ranting and simply say that none of the suggestions I got (which I appreciate!) worked, and rather than spending more time figuring out why, I decided to try something different.

NextPVR is an awesome free (as in beer, not as in freedom unfortunately ...) PVR application for Windows that with a little bit of tweaking handily replaced Windows Media Center. It can even download guide data, which is apparently something WMC no longer feels like doing.

Background I wound up going down this road in a rather circuitous way. My initial goal for the weekend project was to get Raspbmc running on one of my Raspberry Pis. The latest version of XBMC has PVR functionality so I was anxious to try that out as a …

Setting Up Django On a Raspberry Pi

This past weekend I finally got a chance to set up one of my two Raspberry Pis to use as a Django server so I thought I'd share the steps I went through both to save someone else attempting to do this some time as well as get any feedback in case there are different/better ways to do any of this.

I'm running this from my house (URL forthcoming once I get the real Django app finalized and put on the Raspberry Pi) using dyndns.org. I don't cover that aspect of things in this post but I'm happy to write that up as well if people are interested.

General Comments and Assumptions

Using latest Raspbian “wheezy” distro as of 1/19/2013 (http://www.raspberrypi.org/downloads)We’lll be using Nginx (http://nginx.org) as the web server/proxy and Gunicorn (http://gunicorn.org) as the WSGI serverI used http://www.apreche.net/complete-single-server-django-stack-tutorial/ heavily as I was creating this, so many thanks to the author of that tutorial. If you’re looking for more details on …

The Definitive Guide to CouchDB Authentication and Security

With a bold title like that I suppose I should clarify a bit. I finally got frustrated enough with all the disparate and seemingly incomplete information on this topic to want to gather everything I know about this topic into a single place, both so I have it for my own reference but also in the hopes that it will help others.Since CouchDB is just an HTTP resource and can be secured at that level along the same lines as you'd secure any HTTP resource, I should also point out that I will not be covering things like putting a proxy in front of CouchDB, using SSL with CouchDB, or anything along those lines. This post is strictly limited to how authentication and security work within CouchDB itself.CouchDB security is powerful and granular but frankly it's also a bit quirky and counterintuitive. What I'm outlining here is my understanding of all of this after taking several runs at it, reading everything I could find on the Internet (yes, the whole Internet!), and a great deal…