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.
Prerequisites
First, install the required dependencies:
|
|
Next, we’ll need to tweak the entry point of our Javascript. For the default install, this will be in resources/js/app.js
. Add these lines:
|
|
Please note that all of our Stimulus controllers need to be created inside the resources/js/controllers
directory.
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 routes/web.php
file.
|
|
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 app/Http/Kernel.php
file:
|
|
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 ValidationException
exception.
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 202
.
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-controller
and data-action
into our form.
For example, if we have a form like this:
|
|
Change it to be
|
|
Conclusion
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.