How can I pass property to dynamic Vue component in code

35 views Asked by At

I'm using Vue2 and TypeScript and I want to pass multiple properties to a Vue component in code. The component is not mounted via a template but in code. I dynamicly create an element in the DOM and later mount the component on the element.

Vue2 component 'ActivityStream':

<template>
<div id="activity-stream">
  <md-list>
    <activity-list-item v-for="item in items" :key="item.getId()" :activity="item" :language="language"/>
  </md-list>
</div>
</template>

<script lang="ts">
import Vue from "vue";
import { Activity } from "models/Activity";
import { Component, Prop } from "vue-property-decorator";
import MdList from "vue-material/dist/components/MdList";
import MdIcon from "vue-material/dist/components/MdIcon";
import ActivityListItem from "components/ActivityListItem.vue";

Vue.use(MdList);
Vue.use(MdIcon);

@Component({
    components: {
        ActivityListItem
    }
})
export default class ActivityStream extends Vue {
    name: "activity-stream";
    @Prop()
    count: number;
    @Prop({ type: LanguageDefinitionNL })
    language: ILanguageDefinition;
    items: Activity[] = new Array<Activity>();
</script>

Create and mount the element dynamicly in code (Typescript):

stream = document.createElement('activity-stream');
stream.setAttribute("id", "stream");
stream.setAttribute("count", "20");
var ActivityStreamClass = Vue.extend(ActivityStream);
this._activityStream = new ActivityStreamClass();
this._activityStream.$mount('#stream');

First of all the 'count' attribute is not picked up by the Vue component and turns out to be undefined. Secondly I don't know how to pass a non-static property like a data model in code (e.g. the 'language' property in this example). Can it be passed in the constructor of the Vue (e.g. new ActivityStreamClass({..})) or should I make my own setter methods on the component class? ActivityStream.setCount(count: number))

1

There are 1 answers

0
Huupke On BEST ANSWER

As I didn't find any standard Vue(2) way for doing this I just added methods to my component which kind of looks logical to do:

<template>
    <div id="activity-stream">
      <md-list>
        <activity-list-item v-for="item in items" :key="item.getId()" :activity="item" :language="language"/>
      </md-list>
    </div>
  </template>
  
  <script lang="ts">
  import Vue from "vue";
  import { Activity } from "models/Activity";
  import { Component, Prop } from "vue-property-decorator";
  
  import MdList from "vue-material/dist/components/MdList";
  import MdIcon from "vue-material/dist/components/MdIcon";
  import ActivityListItem from "components/ActivityListItem.vue";
  import { LanguageDefinitionNL } from "tools/i18n/LanguageDefinitionNL";
  import { ILanguageDefinition } from "tools/i18n/interfaces/ILanguageDefinition";
  
  Vue.use(MdList);
  Vue.use(MdIcon);
  
  @Component({
    components: {
      ActivityListItem
    }
  })
  export default class ActivityStream extends Vue {
    name: "activity-stream";
    @Prop()
    count: number;
    @Prop({ type: LanguageDefinitionNL })
    language: ILanguageDefinition;
    items: Activity[] = new Array<Activity>();
    
    public setCount(count: number): void {
      this.count = count;
    }

    public setLanguage(language: ILanguageDefinition): void {
      this.language = language;
    }

    public addItem(activity: Activity): void {
      // Add new item at the top of the list
      this.items.unshift(activity);
    }
  }
  </script>

And when I'm using the component from plain Typescript/Javascript I do the following:

var ActivityStreamClass = Vue.extend(ActivityStream);
this._activityStream = new ActivityStreamClass();
this._activityStream.setCount(10);
this._activityStream.setLanguage(language);
this._activityStream.$mount('#stream');

Enjoy!