Instanciating extended VueJS components with props data within

Hello everyone,

Let me give you a little bit of context about my problem :

I’m trying to create a system that can add charts on a page with the simple push of a button.
These charts are going to contain elements from a mysql database.

I have a Chart.vue file that contains the template for a single HighChart element. It also contains a prop :

export default {
    name : "Chart",
    props : ["tableToDisplay"],
    

And then I have my main vue that is named “Test.vue”.
It imports the Chart.vue from the component folder and then I basically just need to write :

<Chart :table-to-display="tableToDisplay"/>

to create an instance of a chart of the table contained within the variable : this.tableToDisplay.

But this is not what I want to do : I want to create a chart with the push of a button, so I made some changes :

<div>
    <button @click="createGraph">Add a graph</button>
    <Chart :table-to-display="tableToDisplay"/>
</div>

And with it, I created the method:

        createGraph(event)
        {
            let ChartClass = Vue.extend(Chart)
            console.log(ChartClass)
            let graphInstance = new ChartClass({
                props:{
                    "tableToDisplay": this.tableToDisplay
                }
            })
            graphInstance.$mount()

            let divContainer = event.target.parentElement

            divContainer.append(graphInstance.$el)
        },

That is where my problem is.

Within that method, I want to send a table to display to the newly created Chart, but it seems that I can’t manipulate the props value in that way.

I thought that this piece of code was the solution :

           let graphInstance = new ChartClass({
                props:{
                    "tableToDisplay": this.tableToDisplay
                }
            })

But It turns out that it is not.

When I click the button, a empty chart does appear but the prop “tableToDisplay” is undifined.

I looked at the console and I get a “[Vue warn]: Error in mounted hook: “TypeError: ciphertext is null””. It doesnt matter if I put an argument or not in the ChartClass, I always have this error on the graphInstance.$mount() line.

Can you help me ?

Answer

First, I think you don’t need to programatically instantiate your Chart components. A simple v-for loop will do the trick:

<template>
  <Chart v-for="table of chartTables :table-to-display="table"/>
</template>

<script>
...
data() {
   chartTables: []
},
methods: {
   createChart() {
      // Adding a new table to the array will create a new Chart component.
      this.chartTables.push(this.tableToDisplay)
   }
}
</script>

If this solution suits your needs, go ahead in that way!


That said, if you really need to instantiate a Vue component yourself, you have to use the propsData parameter to pass your props.

    const instance = new ChartClass({
      parent: this, // The parent is your current component
      propsData: {
        tableToDisplay: this.tableToDisplay,
      },
    })
    let divContainer = event.target.parentElement 
    instance.$mount(divContainer)

The parent option is really important: it adds your component to the Vue component dependency tree. Without it, your component won’t have inherited properties (such as the Vuex store, plugins etc.).

Leave a Reply

Your email address will not be published. Required fields are marked *