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

joseph127's avatar

Vue Router within a component

So this is something I hadn't thought about doing before, but actually needed to for a project I am working on. So instead of having a single page app with vue router. 90% of the app will be standard laravel code, only certain pages will contain a vue router. Sounds simple enough I thought?

This is the approach I decided to take.

app.js

require('./bootstrap');

//Global components
Vue.component('header-component', require('./components/Header.vue'));
Vue.component('project-component', require('./components/Project.vue'));
Vue.component('sidebar-component', require('./components/Sidebar.vue'));

Vue.component('landing-page', require('./pages/Landing.vue'));
Vue.component('register-page', require('./pages/Register.vue'));
Vue.component('project-page', require('./pages/Project.vue'));


/**
 * Define the main application, this is where all the vue
 * components, pages and modals etc will be initiated into
 */
const app = new Vue({
    el: 'body',
});

/**
 * Define the router. The router will act as a seemless
 * transition between the projects/modals. The reason
 * for this is to allow transitions between pages.
 */
const router = new VueRouter({
    hashbang: false,
    history: true,
    suppressTransitionError: false
});

//Enable HTML5 mode
router.mode = 'html5';

//Map out the routes
router.map({
    '/:team': {
        name: 'team',
        component: Vue.component('project-page'),

        subRoutes: {
            '/:project': {
                name: 'project',
                component: Vue.component('project-page'),
                subRoutes: {
                    '/:screen': {
                        name: 'screen',
                        component: Vue.component('project-page'),
                    }
                },
            },
        },
    },
});

//Start the router
router.start(Vue.component('project-component'), '#project');

the view

<component is="project-component" inline-template v-cloak>
    <section class="container-project" id="project">
        <router-view></router-view>
    </section>
</component>

The strange thing is, everything works as expected. All the $route.params variables come through from the routes setup, and the template of "project-component" is displaying for the correct routes. But I am having a console error of:

<router-view> can only be used inside a router-enabled app.

upon googling this, I only found situations where vue router was initiated on the root app. in which case a simple Vue.extend does the trick. So whats the best way for going about this? And maybe shed some light on why this error is occurring?

0 likes
7 replies
joseph127's avatar

@diegones This has already been initiated in the bootstrap.js and @Ricardogolez unfortunately the requirements for this project is vue 1.0 but took a look at your git repo... looks alright man! Good work.

@diegones bootstrap.js


window._ = require('lodash');

/**
 * We'll load jQuery and the Bootstrap jQuery plugin which provides support
 * for JavaScript based Bootstrap features such as modals and tabs. This
 * code may be modified to fit the specific needs of your application.
 */

window.$ = window.jQuery = require('jquery');

/**
 * Vue is a modern JavaScript library for building interactive web interfaces
 * using reactive data binding and reusable components. Vue's API is clean
 * and simple, leaving you to focus on building your next great project.
 */

window.VueResource = require('vue-resource');
window.VueRouter = require('vue-router');

window.Vue = require('vue');
Vue.use(VueResource);
Vue.use(VueRouter);
Vue.config.silent = true;

/**
 * We'll register a HTTP interceptor to attach the "CSRF" header to each of
 * the outgoing requests issued by this application. The CSRF middleware
 * included with Laravel will automatically verify the header's value.
 */

Vue.http.interceptors.push((request, next) => {
    request.headers['X-CSRF-TOKEN'] = Laravel.csrfToken;
    next();
});

IO_Digital's avatar

I'm dealing with the same problem. If someone manages to solve this, post the solution please.

IO_Digital's avatar

I think I found the correct way to do things:

In my index.blade.php:

@section('content')
    <div id="app"></div>
@stop

In app.js:

const Router = Vue.component('router', require('./components/Router.vue'));
const Container = Vue.component('container', require('./components/Container.vue'));
const Navigation = Vue.component('navigation', require('./components/Navigation.vue'));
const Home = Vue.component('home', require('./components/Home.vue'));

const app = new Vue({
    el: 'body'
});

var router = new VueRouter({
    hashbang: true,
    history: true
});

router.mode = 'html5';

router.map({
    '/': {
        name: 'home',
        component: Home
    }
});

router.redirect({
    '*': '/'
});

router.start(Router, '#app');

In my Router.vue:

<template>
    <div>
        <container></container>
        <router-view></router-view>
    </div>
</template>

<script>
    import Container from './Container.vue';

    export default {
        data () {
            return {

            }
        },
        components:{
            'container': Container
        }
    }
</script>

Doing it like this seems to work nicely

Please or to participate in this conversation.