0
votes

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}}

3
Since you have extracted your template to a different file you require the path to the file in your template property like template:require('path/to/your/template file') in the Tasks.js. And by the way if you are to use a separate file for component template it has to be a .html file, you cannot use a .blade.php file with vue it won't be able to parse it. I will provide a sample template file below in answerDonkarnash
@Donkarnash. I have successed to get html template. And yes, external template is not .blade, it's html. But now geting new error. Let me update my question.Akshay Vaghasiya
Your tasks template should contain just the markup for your tasks component and there's no need for a <body> tag. Just ensure that your entire markup for the component has a single root element <div class="tasks-component component"> for example.Donkarnash
@Donkarnash. <body> tag is in main html file. So I can't remove it. But in tasks-template.html. There is no any body tag.Akshay Vaghasiya

3 Answers

1
votes

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

0
votes

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.

0
votes

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);