Laravel Spark - Vue components

Laravel Spark is out and it is really exciting to work with. But it is different from building an application from scratch. It provides a lot of great features but this also means quite some new stuff to learn. Today I want to show you how to use a Vue component in Spark.
Note: If your are already using Spark 3, checkout my article Laravel Spark 3 and Vue components.

Laravel and Vue

Vue.js is a lightweight modern JavaScript framework that is very popular these days. Especially when you do not want the overhead of frameworks like Angular or React, Vue is a great choice. Additionally it is great when you do not need a whole SPA (Single page application). Just use your Vue components where you want them.

Components are one of the most powerful features of Vue.js. They help you extend basic HTML elements to encapsulate reusable code.(Vuejs.org)

Taylor Otwell, the creator of Laravel, is a big Vue fan and this is why you will find it in a lot of Laravel products. Spark is using Vue too. A lot of the given features like the authentication, the admin panel or the menu is build with Vue. But it is not a requirement. Of course you can use the front-end framework of your choice, but I can totally recommend it.

Spark and Vue components

This is how a Vue component is created.

var MyComponent = Vue.extend({
  // options...
})

This is the JS part. Additionally you will need some markup for your component which you can add through the template property.

 // Define a vue component
 var MyComponent = Vue.extend({
   template: '<div>A custom component!</div>'
 })
 

One way to define your markup is to add it inside your component. To use this component you would just use custom tags like:

 // Inside your HTML
 <my-component inline-template></my-component>
  

I do not like this approach, because a string is not the best way to store HTML markup. Therefor I prefer the inline template feature of Vue. Here we have a custom tag for my component with an HTML attribute of inline-template. This tells Vue to use the markup inside of these tags. This is much cleaner and your IDE will recognise it.

 // Inside your HTML
 <my-component inline-template>
   <p>These are compiled as the component's own template</p>
   <p>Not parent's transclusion content.</p>
 </my-component>
 

In both cases you will need to write you component styles in your CSS files like always. This is a little disadvantage because your component has parts in multiple locations. It would be much better if all the parts where just in one file.

Vueify to rescue

Vueify lets you write all your component stuff in one file like this:

// myComponent.vue
<style>
  .red {
    color: #f00;
  }
</style>

<template>
  <h1 class="red">{{ msg }}</h1>
</template>

<script>
export default {
  data () {
    return {
      msg: 'Hello world!'
    }
  }
}
</script>

Isn’t that great? Every time you want to change something in your component there is only one place you need to look.

Back to Spark

When I started to use Spark I wanted to use some of my already given .vue components too, but since Spark is a little bit different from standard Laravel projects I didn’t managed to use them. After some weeks of reaching out for help, I finally got the solution. (Big thx to @jstoone)

Here is an example of a .vue component. It just outputs a headline with a certain message. This will be our example .vue file.

<template>
    <h1 class="helloMessage">{{ message }}</h1>
</template>

<script>
    export default {
        props: {},

        data() {
            return {
                message: "Hello .vue component"
            }
        },

        ready() {}

    }
</script>

<style>
    .helloMessage {
        font-size: 32px;
        color: #ac050b;
        margin: 30px 0;
        text-align: center;
    }
</style>

1. Adding a global .vue component

First we want to register this component as a global one. Therefore you need to modify your Spark’s app.js:

// resources/js/app.js
require('spark-bootstrap');

require('./components/bootstrap');

import Hello from './components/Hello.vue'; // (new)

Vue.component('hello', Hello); // (new)

var app = new Vue({
    mixins: [require('spark')],
});

Just the two lines marked with “new” are, well guess, new.

Let’s test it by placing the component inside the home.blade.php view.

@section('content')
<hello></hello>
<home :user="user" inline-template>
    <div class="container">
        <!-- Application Dashboard -->
        <div class="row">
            <div class="col-md-8 col-md-offset-2">
                <div class="panel panel-default">
                    <div class="panel-heading">Dashboard</div>
                    <div class="panel-body">
                        Your application's dashboard.
                    </div>
                </div>
            </div>
        </div>
    </div>
</home>
@endsection

Let’s check if everything is working. Wuhu!

.vue component inside Spark

2. Adding a child component

If you want to use a component inside of another component like the Spark home component, you can do that as well.

// resources/js/app.js
require('spark-bootstrap');

require('./components/bootstrap');

import Hello from './components/Hello.vue';

Vue.component('home', {
    components: {
        Hello
    },
    props: ['user'],

    ready() {
        //
    }
});

var app = new Vue({
    mixins: [require('spark')],
});

We are importing the .vue component again, but then we add it to a already existing component. Now we can use Hello inside of the home component:

@extends('spark::layouts.app')

@section('content')
<home :user="user" inline-template>
    <div class="container">
        <!-- Application Dashboard -->
        <div class="row">
            <div class="col-md-8 col-md-offset-2">
                <hello></hello>
                <div class="panel panel-default">
                    <div class="panel-heading">Dashboard</div>

                    <div class="panel-body">
                        Your application's dashboard.
                    </div>
                </div>
            </div>
        </div>
    </div>
</home>
@endsection

Conclusion

Last time I showed how to start adding a little nav in Laravel Spark. Today it was all about Vue components. Not everybody is a fan of the one file .vue components, but if you are you now know how to use them in your Laravel Spark application. Thx to @jstoone again for providing the solutions!

comments powered by Disqus