Simon Kollross

Simon Kollross

Software developer, blogger, elegant code enthusiast.

Accessing window.App with a Vue.js mixin

Nearly every app which uses Laravel has to export some vars from PHP to use them in JavaScript, e. g. the appUrl or the csrfToken.

The common pattern to accomplish that is by adding a <script> tag to the <head> of the main layout app.blade.php and generate some JavaScript with Blade or pure PHP. If you don’t want to write it manually, you can use the excellent package spatie/laravel-blade-javascript that provides you a Blade directive to export variables.

But let’s just use this simple example with some blade expressions:

<head>
    <title>Laravel</title>
    <script>
        window.App = {
            csrfToken: '{{ csrf_token() }}',
            appUrl: '{{ config('app.url') }}'
        };
    </script>
</head>

When we use Vue in our app we often want to access these exported vars from within a custom component, e. g. when we’re creating forms. We are in a different scope and so we can’t reach window.App directly from our template with an expression.

The easy way to deal with it is to export an additional property globals from the data() function of the component: globals: window.App. But this is becoming awkward when there are a lot of components.

A Vue mixin to the rescue!

With a Vue mixin you can extend Vue instances with custom functionality with an opt-in behavior. Just create a file resources/assets/js/mixins.js and put in the following:

export const globals = {
    data() {
        return {
            globals: window.App
        }
    }
}

It’s simply a partial component. And you can put in nearly everything you can put in a real component. Other components which use the mixin have to explicitly specify it and then it’s merged in your actual instance. Every component that uses the mixin has a globals variable now available as a data property.

<template>
    <span>{{global.appUrl}}</span>
</template>
<script>
import {globals} from "../mixins"
export default {
    mixins: [globals],
    data() {
        return {
            some: 'data'
        }
    }
}
</script>

A big advantage of the mixin solution is that you don’t have to include your mixin in every Vue instance you create (compared to Vue.extend()), but just where you need it. Further it introduces some kind of better structuring, because changes to the global vars are made in one place now.

Have fun with cleaning up your Vue.js components!