Skip to content

Instantly share code, notes, and snippets.

@scottcorgan
Forked from benoitongit/my_vue_component.coffee
Created January 23, 2017 17:36
Show Gist options
  • Save scottcorgan/b35cb59f21acd392d07020a700d017b7 to your computer and use it in GitHub Desktop.
Save scottcorgan/b35cb59f21acd392d07020a700d017b7 to your computer and use it in GitHub Desktop.
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