Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dynamically instantiating a component in Vue.js

Following this tutorial, I'm trying to programmatically create instances of a component on my page.

The main snippet is this:

import Button from 'Button.vue'
import Vue from 'vue'
var ComponentClass = Vue.extend(Button)
var instance = new ComponentClass()
instance.$mount()
this.$refs.container.appendChild(instance.$el)

However I get two errors:

  1. The component I'm trying to instantiate contains references to the store, and these don't work: "TypeError: Cannot read property 'state' of undefined".

  2. For the last line of the snippet (this.$refs.container.appendChild(instance.$el)) I get this error: "Uncaught TypeError: Cannot read property 'container' of undefined"

I'm really not sure how to troubleshoot this, if anyone strong in Vue.js could give me some hint as to why I'm getting these errors and to solve them that would be terrific.

like image 423
drake035 Avatar asked Dec 24 '22 03:12

drake035


2 Answers

1) Since you're manually instantiating that component and it doesn't belong to your main app's component tree, the store won't be automatically injected into it from your root component. You'll have to manually provide the store to the constructor when you instantiate the component ..

import ProjectRow from "./ProjectRow.vue";
import Vue from "vue";
import store from "../store";

let ProjectRowClass = Vue.extend(ProjectRow);
let ProjectRowInstance = new ProjectRowClass({ store });

2) In a Vue Single File Component (SFC), outside of the default export this doesn't refer to the Vue instance, so you don't have access to $refs or any other Vue instance property/method. To gain access to the Vue instance you'll need to move this line this.$refs.container.appendChild(instance.$el) somewhere inside the default export, for example in the mounted hook or inside one of your methods.

See this CodeSandbox for an example of how you may go about this.

like image 124
Husam Ibrahim Avatar answered Dec 25 '22 15:12

Husam Ibrahim


This is another way to instantiate a component in Vue.js, you can use two different root elements.

// Instantiate you main app
var app = new Vue({
  el: '#app',
  data: {
    message: 'Hello Vue!'
  }
})

//
// Then instantiate your component dynamically
//

// Create a component or import it.
const Hello = {
  props: ['text'],
  template: '<div class="hello">{{ text }}</div>',
};

// Create a componentClass by Vue.
const HelloCtor = Vue.extend(Hello);

// Use componentClass to instantiate your component.
const vm = new HelloCtor({
  propsData: {
    text: 'HI :)'
  }
})
// then mount it to an element.
.$mount('#mount');


like image 36
Navid Shad Avatar answered Dec 25 '22 17:12

Navid Shad