I’ve been digging around for a few days trying to find a good example of a fully-functional ajax form using Rails and jQuery. Rails 3 provides a very nice form helper to make forms submit asynchronously, by simply adding this to your form declaration:
:remote => true
Fine. That handles the ajax form submission. But then what? What if you want to do other things after the submission has happened? What about custom ajax events as per the jQuery API? What about response messages and errors?
So I set out to make a fully-functional demo which has all the CRUD operations as ajax submissions. What I wanted was to be able to create, edit and delete all from the index listing without having to navigate to another page. I’m not going to list all the code here because it’s all available in the public repo (github.com/edjames/ajax_forms), but some explanation is needed, so I’ll highlight a few interesting things.
I’ve added some simple validations to the model to illustrate how we could handle these in ajax form submissions. You want your users to know when something cannot be created/saved/deleted, don’t you? More on this later…
The INDEX Action
Nothing out of the ordinary here, but in the view we have extracted the display code for each band into a partial called _band.html.haml. This is important because we will reuse this partial for the create and update actions.
The NEW Action
When a user clicks the “New Band” link, all we want to do is append the form for creation to the list of bands, rather than navigate away from the index page. To do this we bind a jQuery function to the “click” event on the link which submits an ajax request to the “new” action. All the controller does is render a partial which contains the html form. We catch this response in jQuery and append it to our list.
The CREATE Action
The form is submitted via an ajax request. This is done by simply adding a single directive to our form declaration:
:remote => true
If the creation failed, we render the _error.js.haml partial which simply alerts all the error messages on our object. In this case it will be validation failure messages.
The EDIT Action
As with the NEW action, we also bind a jQuery function to our “Edit” links. This function will hide the read-only row in our list, and insert the form html into the list, simulating an in-place edit.
The UPDATE Action
The same as our CREATE action, except instead of simply appending the new read-only html to our list, we now overwrite the existing band’s read-only html with the new content, and then remove the form from the DOM.
The DELETE Action
Custom AJAX events
In the application.js file I have also bound functions to the custom ajax events the fire both before and after an ajax request. All the do is log to the console, but it’s useful to see which events fire and when they fire. Using Firebug you can easily see what this looks like…
Why do you use divs instead of a table?
I use divs because it makes the html fully compliant. Using a table would mean wrapping a TR element with FORM tags, which strictly speaking creates non-compliant html. Although most modern browsers will handle this without any problems, it’s always advisable to err on the side of safety.
I hope you find this post and the accompanying demo app useful. I spent a few days playing with various options, digging into the jQuery API, and scratching around on the web to find something that worked. In the end I had to do this myself to prove the idea.