Search code examples
javascriptphplaravellaravel-5.3vuejs2

How to use external html templates in Components with Vue.js 2.0 in Laravel 5.3


I am using the default Laravel 5.3 setup - a fresh install with default configuration for Vue.js 2.0.

With Laravel 5.1 and Vue.js 1.x, I could easily define components like and used browserify to compile.

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

/*  test-component.js */
export default{
    template:require('./test-component.template.html')
}

/* test-component.template.html  */
<div class="test-component">
    <h1> Test Component <h1>
</div>  

However, with Vue 2, the default is webpack (although browserify is also available but could not get it working and webpack seems better). But I am not able to get the configuration working.

I have tried various configurations, finally I have this in my gulp.js file

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

var config = {

    module:{
        loaders:[
            {
                test: /\.html$/,
                loader: 'vue-loader'
            }
        ]
    }
};
elixir(mix => {
    mix.sass('app.scss')
       .webpack('app.js',null, null, config);
});  

Now I am not getting any errors while compiling gulp webpack however when I try to view the page in the browser, it doesn't show the component and has an error/warn in the console

vue.js?3de6:513[Vue warn]: invalid template option:[object Object] 
(found in component <test>)

vue.js?3de6:4085Uncaught TypeError: Cannot read property 'child' of null(…)  

My app.js main entry file (default provided by Laravel)

require('./bootstrap');

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

const app = new Vue({
    //el: '#app',
}).$mount('#app');  

What am I missing? Any pointers would be appreciated.


Solution

    1. You have to use html-loader instead of vue-loader.

      npm install html-loader --save-dev
      
    2. Your gulpfile.js (need to change the loader):

      const config = {
        module: {
          loaders:[{
            test: /\.html$/,
            loader: 'html'
          }]
        }
      };
      
      elixir((mix) => {
        mix.sass('app.scss')
          .webpack('app.js', null, null, config);
      });
      
    3. Your test-component.js (no changes, you're good to go):

      export default {
        template: require('./test-component.template.html')
      }
      
    4. Your test-component-template.html: (no changes, you're good to go)

      <div class="test-component">
        <h1>Test Component Goes Here</h1>
      </div>
      

    Important

    1. Here's how to define your component:

      • Using Default

        Vue.component('test-component', require('./test-component').default);
        
      • Or, simply use ES2015 import

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