Fanna1119
Fanna1119

Reputation: 2316

Loading inline SVG in vuejs via prop into a component

I am trying to load an inline svg into my component.

App.vue

template

<vue-anime :url="'planetiaermma.svg'" />

anime.vue

  <div>
    <div v-html="this.loadSVG()"></div>
    <img :src="this.svgfile()" alt />
  </div>

  props: ["url"],

  methods: {
    svgfile() {
      var img = this.getImgUrl(this.url);
      return img;
    },
    getImgUrl(pic) {
      return require("../assets/" + pic);
    },

    loadSVG() {
      var img = this.getImgUrl(this.url);
      var svgraw;
      this.$nextTick(() => {
        fetch(img)
          .then(res => res.text())
          .then(svg => {
            svgraw = svg;
          });
      });
      return svgraw;
    },
    mounted() {
      this.loadSVG();
    }
  }
};

firing svgfile() into a :src works

firing loadSVG() should load it inline, does not seem to however, even though the return svgraw; is in a string of html/xml.

Upvotes: 2

Views: 4343

Answers (3)

htmn
htmn

Reputation: 1675

You can simply use something like vue-inline-svg for this:

npm install vue-inline-svg

and register the component globally in your main.js file:

import Vue from 'vue'
import App from './App.vue'
import InlineSvg from 'vue-inline-svg';

Vue.component('inline-svg', InlineSvg);

new Vue({
  render: h => h(App),
}).$mount('#app')

After that you can use the component anywhere inside your templates

Note: if you use vue-loader assets or vue-cli, then paths like '../assets/my.svg' will not be handled by file-loader automatically like vue-cli do for tag, so you will need to use it with require:

<template>
  <div>
    <inline-svg :src="require(`../assets/${url}`)" />
 <!-- You also can specify some props -->
 <!-- width="150" -->
 <!-- height="150" -->
 <!-- :fill="false" -->
  </div>
</template>

and get rid of that messy code.

Upvotes: 2

Fanna1119
Fanna1119

Reputation: 2316

App.vue

<vue-anime :url="'planet.svg'" />

anime.vue component

<template>
  <div>
    <div v-html="mysvgfile"></div>
  </div>
</template>

export default {
  props: ["url"],

  data() {
    return {
      mysvgfile: ""
    };
  },

  methods: {
    svgfile() {
      var img = this.getImgUrl(this.url);
      return img;
    },
    getImgUrl(pic) {
      return require("../assets/" + pic);
    },

    loadSVG() {
      var img = this.getImgUrl(this.url);
      var outer = this;
      this.$nextTick(() => {
        fetch(img)
          .then(res => res.text())
          .then(svg => {
            outer.mysvgfile = svg;
          });
      });
    }
  },
  mounted() {
    this.loadSVG();
  }
};

Upvotes: 0

MohKoma
MohKoma

Reputation: 1472

I'm not sure what are you getting from getImgUrl() but could you try this?

mounted() {
   this.$nextTick(() => {
    this.loadSVG();
   });
}

You might also try this to be sure it's not from missing value:

<img v-if="svgURL" :src="svgURL" alt />


data() {
  return {
    svgURL: null
  }
}

mounted() {
  loadSVG() {
    this.svgURL = 'YOUR VALUE'
  }
}

Please avoid using this inside the template.

Upvotes: 0

Related Questions