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
  • Select an option

  • Save scottcorgan/b35cb59f21acd392d07020a700d017b7 to your computer and use it in GitHub Desktop.

Select an option

Save scottcorgan/b35cb59f21acd392d07020a700d017b7 to your computer and use it in GitHub Desktop.

Revisions

  1. @benoitongit benoitongit revised this gist Dec 19, 2016. No changes.
  2. @benoitongit benoitongit revised this gist Dec 19, 2016. No changes.
  3. @benoitongit benoitongit revised this gist Dec 19, 2016. No changes.
  4. @benoitongit benoitongit revised this gist Dec 19, 2016. No changes.
  5. @benoitongit benoitongit revised this gist Dec 19, 2016. No changes.
  6. @benoitongit benoitongit revised this gist Dec 19, 2016. No changes.
  7. @benoitongit benoitongit revised this gist Dec 19, 2016. 1 changed file with 1 addition and 0 deletions.
    1 change: 1 addition & 0 deletions vue_adapter.coffee
    Original file line number Diff line number Diff line change
    @@ -1,3 +1,4 @@
    # Vue adapter to mount/destroy components
    VueAdapter =
    init: ->
    @vueModels = []
  8. @benoitongit benoitongit renamed this gist Dec 19, 2016. 1 changed file with 0 additions and 0 deletions.
    File renamed without changes.
  9. @benoitongit benoitongit renamed this gist Dec 19, 2016. 1 changed file with 0 additions and 0 deletions.
    File renamed without changes.
  10. @benoitongit benoitongit created this gist Dec 19, 2016.
    8 changes: 8 additions & 0 deletions component.html.erb
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,8 @@
    <%= 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>
    -->
    3 changes: 3 additions & 0 deletions my_component.coffee
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,3 @@
    @MyComponent =
    props: ['myProp']
    template: '<div>A custom component with {{myProp}}</div>'
    36 changes: 36 additions & 0 deletions vue_adapter.coffee
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,36 @@
    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()
    28 changes: 28 additions & 0 deletions vue_helper.rb
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,28 @@
    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