Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I render a new instance of vue component dynamically with dynamic props data

I have a vue component with the following implementation interface.

<my-data-grid :colunms='columns' :rows='rows'></my-data-grid>

I need to render the above component dynamically on multiple tabpages with different data. Each my-data-grid is rendered at different times. It is like ones a new set of data comes in then a new page is created that renders component. Presently It works with columns and rows props updating properly but overrides the data on the other tabpages once a new data comes in.

When I tried to do this dynamically so that the component can be rendered at run time, the component showed but the columns and rows props are not updated. It was showing data() is undefined.

Part of my code is shown below. You can also make reference to this link Render other components in Tab using template

Import MyDataGrid from "./MyDataGridComponent'
Vue.component('my-data-grid', MyDataGrid)
export default {
  name: 'app',
  data: function() {
    return {
      headerText0: {
        text: 'Tab1'
      },
      columns: ['some arrays'],
      rows: ['some arrays'],
      headerText1: {
        text: 'Tab2'
      },
      headerText2: {
        text: 'Tab3'
      },
      Content1: function() {
        return {
          template: Vue.component('MyDataGrid', {
              template: ' <my-data-grid :colunms='columns' :rows = 'rows' > < /my-data-grid>',
              data() {
                return {
                  colunms: this.columns,
                  rows: this.rows
                }
              }
            )
          }
        }
      }
    }
  }

I have searched internet for the past 3 days and I am somehow exhausted. This is my first time asking question on stackoverflow, in case I am off point please forgive me. Thanks in anticipation of your assistance.

like image 932
Damilinks Avatar asked Oct 30 '18 13:10

Damilinks


People also ask

How do I pass Props for dynamic component in Vue?

We can pass props to dynamic components using the v-bind directive. To display dynamic components, we add the component component with the is prop. currentComponent is a string with the component name. v-bind has an object with the props that we want to pass to whatever component is being rendered now.

How do I force a Vue to render a component?

The best way to force Vue to re-render a component is to set a :key on the component. When you need the component to be re-rendered, you just change the value of the key and Vue will re-render the component. This is called the Key-Changing Technique, and it's a pretty simple solution, right?


1 Answers

@Jim thanks for your response, after much searching I was able to get the solution from this article: https://css-tricks.com/creating-vue-js-component-instances-programmatically/. I solve it by using Vue.extend to create a copy of MyDataGrid component as shown below.

  1. The following line imports my vue component

    import MyDataGrid from "./MyDataGridComponent.vue";
    
  2. I pass the MyDataGrid component to Vue.extend to create a subclass of the Vue constructor

    var MyDataGridClass = Vue.extend(MyDataGrid);
    
  3. And then create an instance out of it with the new keyword: propsData provides the data nedded for the columns and rows props in my vue component.

    var instance = new MyDataGridClass({
      propsData: { columns: this.columns, rows: this.rows }
    });
    
  4. I mount the instance on an empty element

    instance.$mount()
    
  5. I used native javascript api to insert it inside a DOM element on my page.

    var tab  = document.getElementById('#mytab')
    tab.appendChild(instance.$el)
    

The complete code is shown below.

import Vue from "vue";
import MyDataGrid from "./MyDataGridComponent.vue";

export default {
data: function () {
  return {
    columns: ['some array'],
    rows: ['some array']
  }
},
methods: {
  addTab() {
    var ComponentClass = Vue.extend(MyDataGrid);
    var instance = new ComponentClass({
      propsData: { columns: this.columns, rows: this.rows }
    });
    instance.$mount()
    var tab  = document.getElementById('#mytab')
    tab.appendChild(instance.$el)
  }
}
};

Sometimes challenges are the fertilizers for creativity. Seek and you shall find.

like image 193
Damilinks Avatar answered Oct 22 '22 12:10

Damilinks