Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Make Vue.js works with Ruby on Rails and Turbolinks 5
@MyComponent =
props: ['myProp']
template: '<div>A custom component with {{myProp}}</div>'
# Vue adapter to mount/destroy components
VueAdapter =
init: ->
@vueModels = []
vueComponents = document.querySelectorAll('[data-vue-component]')
return if vueComponents.length <= 0
self = this
for i in [0...vueComponents.length]
self.mountComponent(vueComponents[i])
mountComponent: (component) ->
name = component.getAttribute('data-vue-component')
props = JSON.parse(component.getAttribute('data-vue-props'))
if typeof window[name] == 'object'
vm = @newVueInstance(name, props)
component.innerHTML = ""
component.appendChild(vm.$el)
@vueModels.push(vm)
newVueInstance: (name, props) ->
element = document.createElement(name)
for key, value of props
element.setAttribute(key, value)
new Vue({
template: element.outerHTML
components: { "#{name.toLowerCase()}": window[name] }
}).$mount()
destroy: ->
for vm in @vueModels
for child in vm.$children
child.$destroy()
vm.$destroy()
@vueModels = []
document.addEventListener 'turbolinks:load', -> VueAdapter.init()
document.addEventListener 'turbolinks:before-cache', -> VueAdapter.destroy()
<%= vue_component 'MyComponent', my_prop: 'awesome prop!' %>
<!--
Final Outpout:
<div data-vue-component="MyComponent" data-vue-props="{&quot;my-prop&quot;:&quot;awesome prop!&quot;}">
<div>A custom component with awesome prop!</div>
</div>
-->
module VueHelper
def vue_component(component_name, props = {}, html_options = {})
html_options = html_options.reverse_merge(data: {})
props = VueHelper.dasherize_props(props)
html_options[:data].tap do |data|
data[:vue_component] = component_name
data[:vue_props] = props.to_json
end
html_tag = html_options[:tag] || :div
html_options.except!(:tag)
content_tag(html_tag, '', html_options)
end
def self.dasherize_props(props)
case props
when Hash
props.each_with_object({}) do |(key, value), new_props|
new_key = key.to_s.dasherize
new_value = VueHelper.dasherize_props(value)
new_props[new_key] = new_value
end
when Array
props.map { |item| VueHelper.dasherize_props(item) }
else
props
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.