In many of todays web applications, AJAX requests have a crucial role in the usability. ou don’t want users to have to refresh the page in order to get the data they requested, especially not if it’s in the middle of a form. However, I often see bad error handling practices when it comes to AJAX requests (read: no error handling at all).
Today, I want to share a method with you that I use in my CakePHP projects. The key is in using Cake’s CakeResponse class, to throw an error and have your AJAX call catch it and run the proper action in response. In my case, I had an AJAX method in my InvoiceLinesController to allow users to add a line to an invoice by using an AJAX call (through a jQuery UI dialog). It essentially does this:
Pretty simple, right? Just take in the passed data and save it as an invoice line. Now, this works well if the user enters proper data. But what if the user enters bad data into the form that doesn’t pass the validation rules you have set in your Model? That’s right, the save will fail. But how are you going to tell your user that?
I extended the method by checking the return status of the save operation and throw the validation errors if it failed:
Now, whenever validation fails, the AJAX call will get the validation errors as returned data. Furthermore (and this is the important bit), it throws a HTTP 400 (Bad Request) status, so the AJAX request will fail and it’s error clause is triggered, rather than it’s success clause as it would on a 200 OK status, which would happen if you don’t set the statusCode with the CakeResponse class.
I also created an element called “error_dialog” to hold and display the HTML content to the user. It’s a very simple element that just ouputs our message and an ordered list using the HtmlHelper nestedList method:
OK, so now you can use the data from your AJAX call to display to the user somehow. I chose to use jQuery UI Modal Dialog message, so it’s bound to get the users’ attention.
I added the following error clause to my AJAX call:
This populates the dialog div with the message thrown by our action. In order to properly display this dialog, you need to add a hidden div to your view (I called it NewInvoiceLineErrorDialog), like this:
Now this div will stay hidden until our error clause is triggered, which will open a popup with the error message. At this point, whenever a user enters bad data, the dialog will pop-up telling them what they have done wrong, so they can fix it and make the save succeed.