podcastfan88
podcastfan88

Reputation: 1070

Return a component's output as part of a method's HTML response in Vue.js

I'm using Material Design's Vue component icon set. I'd like to process a string to include an icon in the middle.

Input (a string I can't control):

"I want an icon to go there"

Desired output:

"I want an <timer-icon></timer-icon> to go there"

I'm trying to do this using a method that processes the text. But how can I get my icon component in there?

I've tried this:

<template>
    <span>{{ insertIcon(myString) }}</span>
</template>

import TimerIcon from 'vue-material-design-icons/Timer.vue'

export default {
   data () {
      return {
        myString: fromAnotherPlugin // "I want an icon to go there"
      }
   },
   components: {
      TimerIcon
   },
   methods: {
      insertIcon: function (string) {
         return string.replace('icon', TimerIcon)
      }
   }
}

But it returns [object Object] in place of "icon."

I've also tried referencing the component as HTML.

<template>
    <span>{{ insertIcon(myString) }}</span>
</template>

import TimerIcon from 'vue-material-design-icons/Timer.vue'

export default {
   data () {
      return {
          myString: fromAnotherPlugin // "I want an icon to go there"
      }
   },
   components: {
      TimerIcon
   },
   methods: {
      insertIcon: function (string) {
         return string.replace('icon', '<TimerIcon></TimerIcon>')
      }
   }
}

But it comes back empty.

Upvotes: 1

Views: 6290

Answers (2)

Justin Kahn
Justin Kahn

Reputation: 1349

If you know what the component is going to be you could just toggle that component using v-if inside your template

<template>
  ... other stuff
  <TimerIcon v-if="showTimer" />
</template>

If you do not want to couple your template to a specific component, you can pass the component down and use v-bind:is or just :is

<component :is="TimerIcon"> </component>

source: https://v2.vuejs.org/v2/api/#component

Upvotes: 0

podcastfan88
podcastfan88

Reputation: 1070

I figured this out based on this tutorial and a suggestion from Justin Kahn. You must create an instance of the component and then you can access the output and other properties.

1) Import Vue and the component into your page:

import Vue from 'vue'
import TimerIcon from 'vue-material-design-icons/Timer.vue'

2) Create an instance of your component

const ComponentClass = Vue.extend(TimerIcon)
const instance = new ComponentClass()

3) Mount and then output the innerHTML on an instance within the function

  insertIcon: function (string) {
      const myicon = instance.$mount()
      const myiconhtml = myicon.$el.innerHTML
      return string.replace('icon', myiconhtml)
  }

The $el object includes other properties, but the innerHTML has what I needed.

Upvotes: 4

Related Questions