views:

48

answers:

1

Several Grails applications, like the one I'm writing, require a /user view and /admin view that are 'dashboards', basically the user or admin lands on that page, possibly after a successful login and all the datatables and tabs are there, so they hardly ever need to navigate off that page, providing a more satisfying users experience, like users of Gmail or Mint have become accustomed.

In order to allow searches and form posts from the main /user dashboard, I've been using the modalbox plug-in v0.4 grails install modalbox. Modalbox obviously is managing the GET/POST itself and unfortunately is losing 99% of the validations that the typical constraints block gives you.

Working around this for now by replacing g:submitButton, putting some basic JavaScript in the submit as shown. (This is a terrible workaround, of course.)

<input type="button" name="create" class="save" onclick="if (!(document.getElementById('name').value === '' || document.getElementById('summary').value === '')) { document.forms[0].submit(); }" value="Create" />

But there must be a better way! I've been told to use g:remoteForm, but have not seen a complete enough example to work w/ Modalbox. Maybe folks are using a new window which would automatically close a couple of seconds like Gmail's compose window?

This is likely a scenario so common as to be ripe for a SiteMesh template, or at the very least a 'render template:' or even a GSP tag like the modalBox:createLink.

Source available here in Gtown project space.

A: 

The example on Modalbox has the validation error already hidden in the lightbox: <p style="display:none">Invalid Email!</p> so I think if you want to use Grails validation, you will have to take control over the form yourself. In this case the lightbox plugin will only be responsible for drawing the lightbox, and you will provide all the form contents.

I use Boxy (another lightbox plugin which should work similarly to your Modalbox) and here's an example of how I use Grails validation within the lightbox. When I create the lightbox I use a "shell" action to fill it. The shell action renders a template, and inside the template is a <g:include> which draws the search form the first time. <g:formRemote> calls a validation action and redraws the contents of the lightbox with the results of the validation action. The results could be either be a success page or a validation error page.

The use of a command object, in this example SearchCommand, is just for demonstration.

Controller:

def launchLightbox = {
    render template: 'lightboxFrame'
}

def lightboxContents = { SearchCommand cmd ->

    // if the search failed, re-draw the search form with validation errors
    if (cmd.hasErrors()) {
        return [cmd: cmd]
    } 

    // the search succeeded. Show the results within the lightbox
    else {
        render template: 'searchResults', model: [results: cmd.results]
    }
}

_lightboxFrame.gsp:

<g:formRemote name="searchLightbox" 
        url="[action: 'lightboxContents']" update="lightboxContentsDiv">
    <div id="lightboxContentsDiv">
        <g:include view="/yourController/_lightboxContents.gsp"/>
    </div>
</g:formRemote>

_lightboxContents.gsp:

<g:renderErrors bean="${cmd}"/>
<p>Enter your search:</p>
<g:textField name="search" value="${cmd?.search}"/>
<g:submitButton name="submitButton" value="Submit"/>

If you want more control over what to do when the search succeeds or fails, for example to either render the validation errors on failure or close the lightbox on success, you'll probably need to write your own javascript callback.

Somewhat related to this problem, and it may be helpful to you, is the Grails Remote Constraints plugin. I haven't tried it in a while, but you should be able to use it to redraw portions of your page asynchronously with validation errors generated by Grails.

Dana
@Dana appreciate the 'render( template: ' approach and the recommendation for Boxy and Remote Constraints.I use ModalBox plug-in a lot for prototyping since (a) looks a bit slicker and more prof'l than Facebox, and (b) it's incredibly easy to add as links or g:link in navigation onclick= "Modalbox.show(this.href, {title: this.title, width: 650, transitions: false, overlayDuration: 1}); return false;" .
mikesalera