1
votes

At this project I'm working on there is a legacy server-rendered web page and some components had problems I've been assigned to fix, and I convinced the team to rewrite those parts in Vue to kickstart our migration.

I wrote the whole mini-app using the Webpack template provided by Vue CLI and it works like a charm... in that specific environment.

If I npm run build the built index.html also works fine in a static server.

However, I can't seem to include the app in an existing page composed of many other elements. Shouldn't it be as simple as adding the <div id='myApp'></div> element to the HTML and loading the generated JS files?

If it helps, the legacy app is a Rails app using .erb templates and the JS files are being loaded through the main pipeline in application.js.

Does anyone know why nothing happens when I try this?

Edit: more information - this is how main.js looks before build:

/* eslint-disable */
import Vue from 'vue'

// UI components
import VueSelect from 'vue-select'

import DynamicForm from './components/DynamicForm/'

Vue.component('vue-select', VueSelect)
Vue.config.productionTip = false

const DynamicForms = new Vue({
   el: '.dynamic-form',
   render: h => h(DynamicForm)
})

Edit: I managed to get Vue to work by integrating Webpack to Rails with Webpacker. However I still have some problems regarding context:

This is my main.js in one of the Vue components. It was working fine until I tried the PropData stunt so I could reuse the component with different data in a few places.

/* eslint-disable */
import Vue from 'vue'

// UI components
import VueSelect from 'vue-select'
// import 'nouislider'

import DynamicForm from './components/DynamicForm/'

import fields from './fields'
import fieldRules from './field-rules'

Vue.component('vue-select', VueSelect)
Vue.config.productionTip = false

document.addEventListener('DOMContentLoaded', () => {
  const el = document.createElement('div')
  document.querySelector('.dynamic-form').appendChild(el)

  const vm = new DynamicForm({
    propsData: {
      fields,
      fieldRules
    },
    el,
    render: h => h(DynamicForm)
  })
})

This is DynamicForm/index.vue

<template>
  <div id='app'>
    <ParamList :fields='paramFields' :fieldRules='paramRules'></ParamList>
    <Output></Output>
  </div>
</template>

<script>
import Vue from 'vue'

import ParamList from './ParamList'
import Output from './Output'

export default Vue.extend({
  props: [ 'fields', 'fieldRules' ],
  name: 'DynamicForm',
  components: {
    ParamList,
    Output
  },
  data () {
    return {
      paramFields: this.fields,
      paramRules: this.fieldRules
    }
  }
})
</script>

<style>
</style>

The field and fieldData props are merely JSON/JSONP with some data I'm going to use inside those components. The idea is that I could write another main.js changing just the field and fieldData when initing the Vue instance.

What am I doing wrong?

1
Can you post your layout and other relevant HTML ERB files?Justin
Looks like you have an unnecessary '#' on your ID think it should be <div id='myApp'></div>. The '#' is used when you want to create css-rules for that id. I.e: #myApp { color: red; } So it should not be included for the id value.ola
Also I see that you have el: '.dynamic-form' so Vue looks for an element with a class named '.dynamic-form'. Try and change that to the name of the id attached to the element that you want to connect Vue to. So if your element looks like this: <div id="myApp"></div> then 'el:' should be: 'el: '#myApp'.ola
@ola it was a typo, thank you for pointing it out. As for the other comment, it seems Vue doesn't like ambiguities. I managed to set up Vue in Rails with Webpacker and the apps I wrote outside of it work, however I'm having trouble with PropData (can't pass external stuff into Vue comps)gchiconi
@Justin I don't think it'll be necessary as I have kind of solved my initial problem already; however it's still no working 100%. I've edited the questiongchiconi

1 Answers

1
votes

I've managed to fix everything in a three-step change to my components.

  1. Integrate Webpack into Rails using Webpacker. There's even a Vue template!
  2. Change the root component (the one mounted at a real DOM element) to a Vue subclass using Vue.extend (so the module line @ the .vue file read export default Vue.extend({ instead of simply export default {
  3. Remove the render function from the new DynamicForm (the name I assigned Vue.extend to) so it renders its own template.

I hope it helps as it was quite a pain to me!