I'm struggling to make this work. I'm developing a VueJS small app, served using ParcelJS.
In a view called DisplayProgram
, I'm trying to create multiple instances of a specific component ModuleListView
, with network fetched data.
When I try to display the components, I get this error : [Vue warn]: Failed to mount component: template or render function not defined.
Here are the two views I'm using :
DisplayProgram.vue
<template lang="pug">
div.grix.xs4
div.col-xs4.row-xs5.row-md8.vself-stretch.vcenter
transition(:name="getSlideSide()" mode="out-in")
component(:is="getModuleListView()")
</template>
<script lang="ts">
import { Component, Prop, Vue } from 'vue-property-decorator';
import ModuleListView from './ModuleListView.vue';
@Component({
components: {
'module-list': ModuleListView
}
})
export default class DisplayProgram extends Vue {
@Prop() program: any;
activeModuleList!: {name: string, number: number, modules: Array<any>};
activeModuleListNumber: number = 0;
previousModuleListNumber: number = 0;
moduleLists : Array<{name: string, number: number, modules: Array<any>}> = [];
listViews: Array<ModuleListView> = [];
async created() {
this.moduleLists = this.getModuleLists(this.program);
this.activeModuleList = this.moduleLists[0];
this.emitModuleListChanged(this.activeModuleList.number);
this.instanciateListViews();
}
instanciateListViews() {
this.moduleLists.forEach(moduleList => {
let moduleListView: ModuleListView = new ModuleListView(moduleList);
Vue.set(this.$options.components, moduleList.number, moduleListView);
this.listViews.push(moduleListView);
});
}
getModuleListView() {
return this.listViews[this.activeModuleListNumber];
}
getSlideSide() {
if (this.previousModuleListNumber > this.activeModuleListNumber) {
return "slide-right";
}
return "slide-left";
}
getProgramProgress() : {actualNumber: number, totalNumber: number} {
return {actualNumber: this.activeModuleListNumber + 1 , totalNumber: this.moduleLists.length};
}
getModuleLists(program: any) : Array<{name: string, number: number, modules: Array<any>}> {
// Getting data and generating the javascript objects
return moduleLists;
}
displayModuleList(index: number) {
this.emitModuleListChanged(index);
}
emitModuleListChanged(moduleListNumber: number) {
this.previousModuleListNumber = this.activeModuleList.number;
this.activeModuleList = this.moduleLists[moduleListNumber];
this.$emit("module-list-changed", {moduleList : this.activeModuleList, total : this.moduleLists.length});
this.activeModuleListNumber = moduleListNumber;
}
}
</script>
<style scoped>
</style>
ModuleListView.vue
<template lang="pug">
div
h2.txt-center.responsive {{moduleList.name}}
</template>
<script lang="ts">
import { Component, Prop, Vue } from 'vue-property-decorator';
@Component({
components: {
}
})
export default class ModuleListView extends Vue {
@Prop() moduleList!: {name: string, number: number, modules: Array<any>};
constructor(moduleList: any) {
super();
this.moduleList = moduleList;
}
async created() {
console.log("modulelistview is created");
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.responsive {
font-size:3vw;
}
</style>
Do you have a solution for this, folks ? Thank you for your help !