Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

christophrumpel's avatar

Spark + Vueify + Custom Vue components

Hey,

I am trying to integrate an existing application to Laravel Spark and I'm having troubles with my Vue components. Vue.js and ES6 is still quite new to me, so I hope you can help me to set this up with Spark.

Let's start with the setup of my existing project where everything is working:

// gulpfile.js
var elixir = require('laravel-elixir');

require('laravel-elixir-vueify');

elixir(function (mix) {
    mix.browserify('main.js')
    mix.scripts([
            ...
        ])
        .sass("styles.scss")
        .version("css/styles.css")
});

// main.js

import Vue from 'Vue';
import AlertSystem from './components/AlertSystem.vue';

new Vue({
    el: 'body',

    components: {AlertSystem},

});

Now in my new Spark application I tried to integrate my Alert component like that.

// Spark app gulpfile.js

var elixir = require('laravel-elixir');
require('laravel-elixir-vueify');

elixir(function (mix) {
    mix.less('app.less')
        .sass("styles.scss")
        .browserify('app.js', null, null, {paths: 'vendor/laravel/spark/resources/assets/js'})
        .copy('node_modules/sweetalert/dist/sweetalert.min.js', 'public/js/sweetalert.min.js')
        .copy('node_modules/sweetalert/dist/sweetalert.css', 'public/css/sweetalert.css');
});

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

require('./components/bootstrap');


import Vue from 'Vue';
import AlertSystem from './components/AlertSystem.vue';


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

So when I log into the application and I get to the "home" view I get this error:

app.js:39283 Uncaught TypeError: Cannot read property 'get' of undefined

which points to this:

this.$http.get('/notifications/recent').then(function (response) {
            _this5.notifications = response.data;

            _this5.loadingNotifications = false;
        });

So can anybody tell me what I am doing wrong and how I can use my given Vue components with vueify in Spark?

0 likes
21 replies
christophrumpel's avatar

Hey,

thanks yes:

<template>
    <div class="alert alert--{{ type }}" v-show="show" transition="fade" @click="show = false">
        <slot></slot>

        <span class="alert__close" v-show="important">x</span>
    </div>
</template>

<script>
    export default {
        props: {
            type: {default: 'info'},
            timeout: {default: 3000},
            important: {
                type: Boolean,
                default: false
            }
        },

        data() {
            return {show: true}
        },

        ready() {

            if (! this.important) {
                setTimeout(
                        () => this.show = false,
                        this.timeout
                )
            }
        }
    }
</script>

<style>
    .alert {
        position: absolute;
        left: 0;
        top: 0;
        width: 100%;
        padding: 20px;

    }

    .alert--info {
        color: #8a6d3b;
        background-color: #fcf8e3;
        border-color: #faebcc;
    }

    .alert--success {
        color: #3c763d;
        background-color: #dff0d8;
        border-color: #d6e9c6;
    }

    .alert-- {
        color: #a94442;
        background-color: #f2dede;
        border-color: #ebccd1;
    }

    .alert__close {
        position: absolute;
        top: 10px;
        right: 10px;
        cursor: pointer;
    }

    .fade-transition {
        transition: opacity .3s ease, transform .3s ease;
    }
    .fade-enter, .fade-leave {
        opacity: 0;
        transform: translatey(-40px);
    }

</style>
christophrumpel's avatar

Anyone already got this working or do you just use the "normal" Vue components?

christophrumpel's avatar

Hey @mikebronner , I got the module in my node_modules folder. But isn't this something that comes with Spark? Because I don't need it for my custom component I want to integrate.

Did you integrate your component similar to how I tried it?

mikebronner's avatar

Hmm, not sure .... from the error it appears that this.$http is not instantiated.

I didn't use vue-resource to post my form in the component I made, but it shouldn't be a problem. Do you have the app on a staging server we could look at? There must be some console errors or warnings?

christophrumpel's avatar

This is really strange because I do not use that too. Unfortunately it is just local. Other question: Do you maybe got a blank Spark installation where you use a single .vue file for demonstration? I need to get this to work =) There must be others too right?=) Thx.

harrysohie's avatar

Have you made any other changes besides just adding your AlertSystem component? If you remove ''' import AlertSystem from './components/AlertSystem.vue'; '''

do you have the same issue?

harrysohie's avatar

From your above comment, it looks like "require('spark-bootstrap');" is commented out.

Maybe check your app.js to be sure that require('spark-bootstrap') is not commented out.

christophrumpel's avatar

Hey @harrysohie ,

thx for helping. It is not commented out. But here s what I did find out: I get the error immediately when I import Vue: import Vue from 'Vue'; // (app.js)

Since then I get the error: "Uncaught TypeError: Cannot read property 'get' of undefined" So this is before importing my component.

Do I need to import Vue like this in Spark?

jstoone's avatar

Hey, this might seem crazy, but since you say:

So this is before importing my component.

I came to think, what if you write import Vue from 'vue', notice the lowercase name. Or else you could just require it like this:

window.Vue = require('vue')

A nice thing to know, is that when you pull in vueify, it automatically pulls in Vue. :)

christophrumpel's avatar

Hey @jstoone ,

you are right, when use the lowercase 'vue', I don't get the "get" error anymore. Guess this is little success here =)

But what I get now is this one:

[Vue warn]: Unknown custom element: <alert-system> - did you register the component correctly?

I tried it like this. Any ideas here too?

require('spark-bootstrap');

require('./components/bootstrap');


import Vue from 'vue';
import AlertSystem from './components/AlertSystem.vue';


var app = new Vue({
    mixins: [require('spark')],
    components: {AlertSystem},
});
1 like
christophrumpel's avatar

hey @jstoone , sure:

PS: I am using js components right now until someone can show me how to use .vue components. Is there really nobody using them in Spark?

<template>
    <div class="alert alert--{{ type }}" v-if="message" v-show="show" transition="fade" @click="show = false">
        <p v-model="message" v-if="message">{{ message }}</p>

        <span class="alert__close" v-show="important">x</span>
    </div>
</template>

<script>
    export default {
        props: {
            type: {default: 'info'},
            timeout: {default: 4000},
            important: {
                type: Boolean,
                default: false
            }
        },

        data() {
            return {
                show: true,
                message: ""
            }
        },

        ready() {

            if (! this.important) {
                setTimeout(
                        () => this.show = false,
                        this.timeout
                )
            }
        },

        events: {
            'pushAlert': function (data) {
                this.message = data.message;
                this.type = data.type;
                this.show = true;
            }
        }

    }
</script>

<style>
    .alert {
        position: absolute;
        left: 0;
        top: 0;
        width: 100%;
        padding: 20px;

    }

    .alert--info {
        color: #8a6d3b;
        background-color: #fcf8e3;
        border-color: #faebcc;
    }

    .alert--success {
        color: #3c763d;
        background-color: #dff0d8;
        border-color: #d6e9c6;
    }

    .alert--danger {
        color: #a94442;
        background-color: #f2dede;
        border-color: #ebccd1;
    }

    .alert__close {
        position: absolute;
        top: 10px;
        right: 10px;
        cursor: pointer;
    }

    .fade-transition {
        transition: opacity .6s ease, transform .6s ease;
    }
    .fade-enter, .fade-leave {
        opacity: 0;
        transform: translatey(-40px);
    }

</style>
2 likes
jstoone's avatar
jstoone
Best Answer
Level 10

Okay I figured it out @christophrumpel.

So if you are getting the following error:

[Vue warn]: Unknown custom element: <test-component> - did you register the component correctly? For recursive components, make sure to provide the "name" option.

It is because you are attaching your AlertSystem-component to the main Vue instance, which is the same thing as you wanting to register the component globally. So, now that we have the global and component keywords, the Vue.js doc says the following:

A component like the above will result in a “max stack size exceeded” error, so make sure recursive invocation is conditional. When you register a component globally using Vue.component(), the global ID is automatically set as the component’s name option. source: http://vuejs.org/guide/components.html#Recursive-Component

So what we learned now is that if we want a global component we should do the following:

import AlertSystem from './components/alert-system.vue';

Vue.component('alert-system', AlertSystem);

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

Now the actual simple reason you are getting your error, is that you are using your <alert-system></alert-system> inside your <home></home>-component.

The Vue app is registered by default on #spark-app-element in resources/views/vendor/spark/layouts/app.blade.php, and spark then @yield('content') and in the home.blade.php-file it, as we expected, uses the <home></home>-component in the "content" section.

So as a round-up, if you want your component to be available everywhere you should do:

import BestComponentEver from './components/best-component-ever.vue';

Vue.component('best-component', BestComponentEver);

But if you just want to add your AwesomeEditor-component to, let's say, the pre-existing home-component you can make add the component as you were trying:

// the home-component is located in ./components by default
// therefore we just import from ./
import AwesomeEditor from './awesome-editor.vue';

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

    ready() {
        //
    }
});

Now the component is registered we can in resources/views/home.blade.php add our new AwesomeEditor-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">
                <div class="panel panel-default">
                    <div class="panel-heading">Dashboard</div>

                    <awesome-editor></awesome-editor>

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

I do hope that this makes sense.

3 likes
christophrumpel's avatar

@jstoone you are my hero =)

Both version worked! Awesome! Thx a lot!! If you don't mind then I would write a little blog article about so that others won't run into the same troubles as I did. Of course I would mention you if that's ok.

1 like
brajt's avatar

I'm using them. I do it like this:

Vue.component('card', require('./custom-components/cards/card.vue'));

I change them to normal imports though when I want to use such a component under the control of vue-router. Then I refer to this component in Router.map and it still works.

=============================

Lol, sorry, I've read only first page of this thread and didn't notice the answer. ;)

1 like

Please or to participate in this conversation.