
January 26, 2019
Vue wrapper for Rails
Normally when I want to add a Vue.js app to my Rails app (using webpacker), I will have a javascript pack with code containing something like this:
// app/javascript/packs/application.js import Vue from 'vue/dist/vue.esm' import TurbolinksAdapter from 'vue-turbolinks' import App1 from '../app1.vue' import App2 from '../app2.vue' Vue.use(TurbolinksAdapter) document.addEventListener('turbolinks:load', () => { const element = document.querySelector("#app-1") if (element != undefined) { const app1 = new Vue({ el: element, template: "<App1 />", components: { App1 } }) } }) document.addEventListener('turbolinks:load', () => { const element = document.querySelector("#app-2") if (element != undefined) { const app1 = new Vue({ el: element, template: "<App2 />", components: { App2 } }) } }) // repeat that fat block for all apps you need to include...
That's way too much repetitive code for me. Luckily, thanks to Chris over at GoRails, I learned about a way to automatically bind your Vue apps to with far less code.
Replace that monstrosity above with this:
// app/javascript/packs/application.js import Vue from 'vue/dist/vue.esm' import TurbolinksAdapter from 'vue-turbolinks'; import App1 from '../app1.vue' import App2 from '../app2.vue' Vue.use(TurbolinksAdapter) // this is the really cool part (part 1) Vue.component('app1', App1) Vue.component('app2', App2) // repeat that one line for all apps you need to include!... document.addEventListener('turbolinks:load', () => { const app = new Vue({ // this is the really cool part (part 2) el: '[data-behavior="vue"]', }) })
Then, in your layout.html.erb
file, add this simple data attribute to the div surrounding your yield tag:
<div data-behavior="vue"> <%= yield %> </div>
Now, all your components defined by Vue.component
are available in your erb view! You can even pass data to them like you would in the template files.
Here is an example:
<app1 :someData="<%= @some_model.to_json %>"></app1>
Pretty cool!