I had a chance earlier this month to convert a fairly generic CRUD-y application that I built in Laravel into something that a little bit more interactive. Since I already got all the interaction nailed down in Laravel including form validation and routing, I decided to use Turbolinks and Stimulus to make the application snappier and behave more like a single page application.
Since both Turbolinks and Stimulus come from the same developer, they pair quite nicely. However, to make them play nice with Laravel, few things need to be taken care of before.
Note: The rest of this article will be based on the default Laravel install, so you probably need to tweak it accordingly based on your application.
First, install the required dependencies:
resources/js/app.js. Add these lines:
Please note that all of our Stimulus controllers need to be created inside the
One last step we need to do for the initial setup is to add support for the class property during our Babel compilation. Add this line into the
.babelrc file. You might need to create one if it doesn’t exist.
By now, Turbolinks is enabled and will start intercepting all requests by default.
Adding a global middleware to our Laravel application
As mentioned, all normal requests should now get intercepted by Turbolinks. However, it might not be able to handle our redirection properly if we define something like this in our
To solve this issue, we can create a global
web middleware that’ll get executed on every request. I created this
app/Http/Middleware/SetTurbolinksHeader.php and set it to load in the
web middleware group.
And in our
I’ll explain about the line
in the next section.
Adding a dedicated FormRequest based class
In my application, I make heavy use of Form Request validation for all of the form submissions. I created a
TurbolinksFormRequest that extends the default Laravel’s
FormRequest class that overrides the
failedValidation method. The whole class is pretty simple, it creates a new response, with all the user inputs and any validation errors and throws a new
The content of the class is as follows:
There is no reliable way for me to get the array of
$dontFlash from the
app/Exception/Handler.php file so I decided to just copy the array again into this class. Now, all we need to do is to change any
FormRequest instance that we have in our controllers with
TurbolinksFormRequest and we’re good to go. The middleware that we have before will automatically set the content to the redirected URL and set the status code to
For example, if we have something like this in our route file:
We can convert it to:
Stimulus-powered AJAX Form
The last step is to convert all of our forms to the Stimulus version of it. To begin, create a new controller inside the
resources/js/controllers folder. I’ll name it
ajaxform_controller.js to follow the naming convention mentioned in its handbook.
At its very basic form, the controller will look like this:
Remember the line in custom middleware that we created previously?
Now all AJAX requests will return a redirect URL in the response body. So all this class needs to do is to prevent default form submission and do a request using Axios library instead. We then can use the retuned URL to redirect form submission using the
Turbolinks.visit(res.data). To use this controller in our existing forms, add the related attribute
data-action into our form.
For example, if we have a form like this:
Change it to be
Integrating Turbolinks and Stimulus into r Laravel application is fairly easy to do. With minimal changes in the existing codebase and the fact that they pair nicely together, it can be a powerful combination to use to make our app feels snappier and behaving more like single page application.