Javascript in Laravel (single Vue instance)

A single Vue instance

Pim Hooghiemstra
PLint-sites
4 min readMay 14, 2018

--

Update May 2021

Please note that this post is currently 3 years old. As you know, things move fast in our tech world and event though the principles described in this post are still valid, there might be better ways to achieve the same result; You are free to continue reading, but I recently wrote a post about our current approach.

Additionally, Laravel 8 brings a new starter kit to quickly scaffold the frontend of your next project. It’s called Laravel Jetstream and is definitely worth taking a look. I’ll choose Laravel Jetstream with Inertia scaffolding for my next project.

Therefore, I am removing the code repository that originally came with this post.

Original post

This is the fourth post in our Javascript in Laravel series. We have discussed the series overview and sample project, discussed the jQuery way and continued with Laravel Mix as module bundler. Finally we introduced Vue.

In this post we’ll use Vue to implement the Javascript behaviour we initially developed with jQuery. We will create a single Vue instance for our sample application that will be loaded in the main layout file app.blade.php.

A single tree…

The details of the code

Starting from the previous jQuery code base (branch introduce-webpack), we need to import Vue to start. We’ll do this in the bootstrap.js file and make it a global variable by attaching it to the window.

Next up is app.js. We require the bootstrap.js file and create a new Vue instance like so

To be able to implement the same behaviour as before, we need to make some changes:

  • Add v-model directives to the form.
  • Add a loading indicator and make sure it is shown at the right moment.
  • Add info/ error messages for the user to know if all input is ok.

Below is the new version of the form form.blade.php that can be used by Vue

Then it is time to show the Vue code that makes the blade view above interactive:

As you can see in the data section of the code, we have a boolean for the loading indicator in l. 24 of form.blade.php.

Furthermore, the following 4 variables (gender, email, zipcode and country) are used for the 4 form fields:

  • gender is used as a v-model for the radiobuttons where the user can select their gender.
  • email is an object, the value property is the v-model for the email input field, and the msg and class properties are for showing the info or error message in the right way.
  • The same holds true for zipcode and country.

In form.blade.php we added various event callbacks that are summarised in the methods object. The logic of these callback functions is comparable to the jQuery version discussed earlier. The main difference is that we no longer need to manipulate the DOM directly. Instead, we change the data property in Vue and this causes a rerender of (parts of) the form.

In general I think that implementing Javascript behaviour this way makes much more sense to the brain. We just change some data (based on the business logic of the app) and the rest is taken care of by Vue.

Things to think about

In this very simple example we only have a single page which needs some Javascript.

Typically, a web application consists of multiple pages, each with some Javascript applied to them. Continuing the way discussed so far would lead to an app.js file that gets very large. Additionally, the number of items in the data and method objects would increase dramatically, which makes the code hard to maintain.

So, perhaps we could use the single Vue instance per page approach?

A single Vue instance per page

This approach means that we create an app.js file for each page (of course we name these files differently 😊). Subsequently, we need to update the webpack.mix.js file to be able to compile all these files. That is quite easy though, we simply add some more rows like this

And then we would use the compiled version directly in the view like so. Note that we no longer load app.js in the main layout as each page gets its own version:

This approach makes sure that only the Javascript code for the page we are on is loaded and nothing more. However, if we are using the same datepicker on multiple pages, a lot of code repetition is needed to make it work.

I have used this approach in a personal project. Although it works, the code is rather difficult to maintain and it seems overly complex when I look at this code now.

We definitely need components

In an upcoming post, we’ll discuss an improved approach I call the single Vue instance for the entire application approach. We still instantiate a single Vue instance as we have done here, but this instance does not hold data and/ or methods. Instead, it imports single file components which may be used throughout the blade views in the application.

--

--

Pim Hooghiemstra
PLint-sites

Love to build Laravel + Vue applications! Founder of PLint-sites. https://plint-sites.nl