Akshay Vaghasiya
Akshay Vaghasiya

Reputation: 1637

Getting error "Failed to mount component: template or render function not defined." while using js file as Vue component

I'm using Vue in Laravel 5.3. I have already worked with Laravel 5.2. But Laravel 5.3 and Vue.js is new for me. So I'm playing with these pair. I have completed Laravel Passport tutorial successfully. Now what I want to do is put my html template in blade file and js code in Vue component. But I'm getting this error:

[Vue warn]: Failed to mount component: template or render function not defined. (found in component )

So I can't understand reason of this error as I'm new in Vue.js. If any one knows answer, it will be appreciated. Here is my code.

Blade file

<body>
    <div id="app">
        <tasks></tasks>
    </div>
    <template id="tasks-template">
        <ul class="list-group">
            <li class="list-group-item" v-for="task in list">
                @{{task.body}}
            </li>
        </ul>
    </template>
    <script src="/js/app.js"></script>
</body>

/resources/assets/js/app.js

require('./bootstrap');
Vue.component('tasks', require('./components/Tasks'));
const app = new Vue({
    el: '#app'
});

/resources/assets/js/components/Tasks.js

export default {
    template: '#tasks-template',
    data: function () {
        return {
            list: ''
        };
    },
    created: function() {
        this.$http.get('/api/tasks').then((response) => {
            this.list = response.body;
        }, (response) => {
            alert(0);
        });
    }
}

UPDATE

Blade file

<body>
    <div id="app">
        <tasks></tasks>
    </div>
</body>

/resources/assets/js/components/Tasks.js

template: require('../components/tasks-template.html'),

instead of

template: '#tasks-template'

/resources/assets/js/components/tasks-template.html

<ul class="list-group">
    <li class="list-group-item" v-for="task in list">
        {{task.body}}
    </li>
</ul>

But now getting this error.

Uncaught Error: Module parse failed: /var/www/html/casesync/resources/assets/js/components/tasks-template.html Unexpected token (1:0) You may need an appropriate loader to handle this file type. | | | @{{task.body}}

Upvotes: 0

Views: 3087

Answers (3)

Davide Casiraghi
Davide Casiraghi

Reputation: 18087

I had the same problem importing a vue component. You have to change

Vue.component('tasks', require('./components/Tasks'));

change it to

Vue.component('tasks', require('./components/Tasks').default);

Upvotes: 0

Abhishek Kushwaha
Abhishek Kushwaha

Reputation: 1519

It should be require('./components/Example.vue').default. Since v13, vue-loader exports the component as the default key, which still works the same when using import, but requires the above when using require.

Upvotes: 0

Donkarnash
Donkarnash

Reputation: 12835

Lets say you have your template file as

/*  resources/assets/js/components/tasks.template.html */

<div class="tasks-component component">
    <ul class="list-group">
        <li class="list-group-item" v-for="task in list">
            {{task.body}}
        </li>
    </ul>
</div>  

Then the Tasks.js would be

/*  resources/assets/js/components/Tasks.js  */

export default {
    template: require('./tasks.template.html'),
    data: function () {
        return {
            list: ''
        };
    },
    created: function() {
        this.$http.get('/api/tasks').then((response) => {
            this.list = response.body;
        }, (response) => {
            alert(0);
        });
    }
}

The you can have your app.js as

/*  app.js  */

require('./bootstrap');
Vue.component('tasks', require('./components/Tasks').default);
const app = new Vue({
    //el: '#app'
}).$mount('#app'); 

//your main index.php or entry point could be  
<body>
<div id="app">
    <tasks></tasks>
</div>
</body>  

UPDATE

For the default/out-of-box webpack configuration to work on Laravel5.3, you will need to pull in html-loader through npm

npm install html-loader --save-dev  

Then in the gulpfile.js - specify html-loader to be used for .html files.

const elixir = require('laravel-elixir');
require('laravel-elixir-vue-2'); 

const config = {
  module: {
    loaders:[
        {
            test: /\.html$/,
            loader: 'html'
        }
    ]
  }
};

 elixir((mix) => {
   mix.sass('app.scss')
     .webpack('app.js', null, null, config);
 });  

Finally you can register global components in your main/entry file app.js as

Vue.component('test-component', require('./test-component').default);

/*  Or using ES2015 import */

import TestComponent from './test-component';
Vue.component('test-component', TestComponent);  

I got help from @Alfa here

Upvotes: 1

Related Questions