0
votes

I've run through many different Stackoverflow posts and many had my symptoms yet none of the solutions fixed my problem. Apparently, according to this post many, many things can cause this issue. I decided to upgrade all my npm, node and vue to the latest and make a minimal code example of my problem (the Condition component contains a template with a single root div containing 3 vuetify text fields):

<template>
  <div id="app">
    <v-btn @click="addCondition()" color="secondary" dark>Add Condition</v-btn>
    <div id="conditions">
      <template v-for="condition in conditions">
        <component :is="condition" :key="condition.id"></component>
      </template>
    </div>
  </div>
</template>

<script>
// none of the below work
//import Condition from '@/components/Condition.vue';
//const Condition = require('@/components/Condition.vue').default
Vue.component('Condition', require('@/components/Condition.vue').default);
import Vue from "vue";

export default {
  name: "Test",
  components:
  {
    Condition
  },
  methods: {
    addCondition()
    {
      const ConditionClass = Vue.extend(Condition);
      const conditionInstance = new ConditionClass(); //{ propsData: { id: conditions.length, value: 0 }});
      this.conditions.push(conditionInstance);
    }
  },
  data() {
    return {
      conditions: []
    };
  }
};
</script>

<style>
</style>

When I click the Add Condition button, I get the oft encountered and dreaded "[Vue warn]: Failed to mount component: template or render function not defined." message in the console. Realizing that the error may be caused by things in my configuration, I also put all the code for the vue project in https://github.com/mentaloaf/stackoverflow_vuejs.git. As I've lost a day on this I'm hoping there's a silly/simple fix.

Also thought I would post relevant toolchain versions:

/tmp/comptest/stackoverflow_vuejs master ?1 ❯ vue -V                                                                                                                                                                                                                                        3m 30s
@vue/cli 4.5.12
/tmp/comptest/stackoverflow_vuejs master ?1 ❯ npm -v
7.5.4
/tmp/comptest/stackoverflow_vuejs master ?1 ❯ node -v
v15.9.0

Cheers!

1

1 Answers

0
votes

The problem is that you are instantiating the component and sending that instance to your dynamic component, instead of that you should be registering the component (you are already doing that) and for your dynamic component you need to send only the name of the registered component.

The component registration is happening here:

Vue.component('Condition', require('@/components/Condition.vue').default);

In order to use that component in a dynamic manner you only need to do:

<component :is="'Condition'"/>

as you can see, only the name is needed (as a string) and Vue make the instance of the component.

Here is your code working:

<template>
 <div id="app">
  <v-btn @click="addCondition()" color="secondary" dark>Add Condition</v-btn>
  <div id="conditions">
   <template v-for="condition in conditions">
     <component :is="condition" :key="condition.id"></component>
   </template>
  </div>
 </div>
</template>

<script>
// This component registration only needs to happens once, it could also be in another file
Vue.component("Condition", require("@/components/Condition.vue").default);
import Vue from "vue";

export default {
  name: "Test",
  components: {}, // No need for the component here since you are not using it
  methods: {
    addCondition() {
      // NO need for instances here, nor for Vue.extend because Condition is already a component
      this.conditions.push("Condition");
    },
  },
  data() {
    return {
      conditions: [],
    };
  },
};
</script>