Creating Virtual Nodes from a string with HTML tags in Vue 2.5: A Step-by-Step Guide

Having some trouble creating a functional component that displays the Feather Icons package - I'm stuck on the final step. Here's what I have so far:

This is my FeatherIcon.vue component.

<script>
const feather = require("feather-icons");

export default {
  components: {},
  props: {
    type: {
      required: true,
      type: String
    }
  },
  mounted() {},
  render(createElement) {
    return createElement(
      "svg",
      {attrs: feather.icons[this.type].attrs },
      feather.icons[this.type].contents
    );
  }
};
</script>

In Vue documentation, it says that the 3rd argument should be either:

// {String | Array}
// Children VNodes, built using `createElement()`,
// or using strings to get 'text VNodes'. Optional.

However, the value of my 3rd argument feather.icon[this.type].contents is a string containing the "innerHTML" inside the svg tag:

"<line x1="6" y1="3" x2="6" y2="15"></line><circle cx="18" cy="6" r="3"></circle><circle cx="6" cy="18" r="3"></circle><path d="M18 9a9 9 0 0 1-9 9"></path>"

So my question is, how can I convert feather.icon[this.type].contents into a set of VNodes?

I've attempted using DOMParser and parseFromString but haven't had any success. Any suggestions?

Answer №1

You have the option to utilize the domProps property within the data object.

This feature enables you to bind standard HTML attributes and DOM properties like innerHTML (replacing the v-html directive).

Below is an illustration.

console.clear()

const content = `
  <line x1="6" y1="3" x2="6" y2="15"></line>
  <circle cx="18" cy="6" r="3"></circle>
  <circle cx="6" cy="18" r="3"></circle>
  <path d="M18 9a9 9 0 0 1-9 9"></path>
`

new Vue({
  el: "#app",
  render(h){
    return h("svg", {domProps:{innerHTML: content}})
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.min.js"></script>
<div id="app"></div>

In your scenario, simply assign innerHTML to the feather's content.

Moreover, if you lack a template, typically, a standalone javascript file suffices. A single file component isn't necessary. Hence, your component could be as follows:

FeatherIcon.js

const feather = require("feather-icons");

export default {
  props: {
    type: {
      required: true,
      type: String
    }
  },
  render(createElement) {
    return createElement(
      "svg",
      {
        attrs: feather.icons[this.type].attrs,
        domProps: {
          innerHTML: feather.icons[this.type].content
        }
      });
  }
};

Lastly, if you aim to convert this into a functional component, you can implement something like this:

const FeatherIcon = {
  functional: true,
  props: {
    type: {
      required: true,
      type: String
    }
  },
  render(h, context){
    const {contents, attrs} = feather.icons[context.props.type]
    return h("svg", {attrs, domProps: {innerHTML: contents}})
  }
};

Here is a demonstration of it in action.

console.clear()

const FeatherIcon = {
  functional: true,
  props: {
    type: {
      required: true,
      type: String
    }
  },
  render(h, context){
    const {contents, attrs} = feather.icons[context.props.type]
    return h("svg", {attrs, domProps: {innerHTML: contents}})
  }
};

new Vue({
  el: "#app",
  components: {
    FeatherIcon
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.min.js"></script>
<script src="https://unpkg.com/feather-icons"></script>
<div id="app">
  <feather-icon type="eye"></feather-icon>
  <feather-icon type="activity"></feather-icon>
  <feather-icon type="award"></feather-icon>
</div>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Modify the content in the v-navigation-drawer upon clicking

I am currently working on a project with a v-navigation-drawer and two buttons. The first button is designed to open the drawer, while the second one should change the content of the drawer without closing it. I want the content to update instantly without ...

Exploring the power of Vue i18n for prop translations in Vue applications

My goal is to translate the titles passed to my component through props. However, it seems that these strings are not being translated like the rest of my code due to being passed as props. Below are the two components I am currently working with: Parent ...

Are there any situations in which subscribing to an RXJS Observable does not result in either a success or error response

I have a question rather than a problem to resolve. I am curious if there is a scenario where neither "Success" nor "Error" are triggered. When making a POST call to "/logout", the expected response is an HTTP status code of 200 with an empty body. impo ...

handling axios retries in main.js within a Vue.js application

I have a method called getUsers within the created hook of the Users Component. Additionally, I have both an access token and refresh token stored in my local storage. What I aim to achieve is that when my access token expires, I can use the refresh token ...

I am having difficulty toggling text within a for loop in JavaScript

When I display a list of cards using a for loop and click on them, I want to toggle some text. The issue I'm facing is that it works fine for the top card, but when I click on the card below, it toggles the text of the first card instead. This is desp ...

Exploring the architecture of Redux-thunk and validating the impact of side effects

I've been using redux-thunk and I'm not entirely sure if my side effects (specifically the showAlertError function) are structured properly. While my jest test setup seems to be fine at first glance, I encountered an error: jest.fn() value mus ...

Troubleshooting problems with dynamic imported asset URLs in Vue and Vitest snapshot snapshots

After migrating my project from Vue-CLI & Jest to Vite & Vitest, I encountered a problem when trying to run tests through Jenkins. It seems that some snapshot images are failing to match due to discrepancies in asset paths. Expected : src="file:///C: ...

Decode PDF417 barcode images with ease using HTML and JavaScript on both desktop and mobile web browsers

Looking to utilize JavaScript to decode PDF417 type barcode images? If you're encountering Zxing plugin issues in mobile browsers but it works well on desktop browsers with https://github.com/PeculiarVentures/js-zxing-pdf417, consider alternative sol ...

Show only the present y-coordinate in the ToolTip of a chart.js

I am currently working on developing a chart using Chart.js, and my goal is to only show the y-axis value in the tooltip. The current display shows: date name_of_line: measurement example: Jan 1, 2020, 8:00:00 AM 5th Percentile: 100 oz. However, I would ...

Encountered an error while trying to run npm start

I set up a Vagrant virtual machine, installed Node.js (v 6.9.1), and NPM (v 4.0.0). After cloning a Node.js app using Git clone, I ran the npm install command in both the root folder and the app folder. However, when attempting to start the app with npm st ...

AntD Functional Component with Row Selection Feature

Is there a way to retrieve the key of a single element in the table instead of getting undefined? How can I extract the id? Check out this link for more information. const [select, setSelect] = useState({ selectedRowKeys: [], loading: false, }); ...

What is the best way to combine multiple periods into a single range?

I am on a quest to find a way to transform sound frequency into light frequency, essentially turning sound into color. Currently, I have managed to come up with a straightforward formula that converts the sound frequency into the light frequency range: co ...

Error occurs when trying to create or delete a folder in Express.js

Implement Folder Creation Code in index.js let companydir = './views/campaigns/' + companyname; if(!fs.existsSync(companydir, { recursive: true })) { fs.mkdirSync(companydir, { recursive: true }); } var dir = companydir + &apo ...

Encountering an error when attempting to access undefined property while using a method as a callback

Exploring OOP and angular is new to me. I am currently trying to implement a reusable table with pagination that triggers an API request when the page changes (pagination within the table component). The issue arises when I attempt to access my method usi ...

Stop working to $(this) in jquery when clicking outside

I'm facing an issue with my code and would like some help. I have a button that toggles the visibility of a filter element, which is working fine. However, I now want to implement a "click outside" effect to close the filter when clicking on any body ...

Having trouble invoking html2canvas within an AngularJS app

When I define html2canvas functions in my controller, the alert in html2canvas doesn't get fired and my canvasToImageSuccess function is not executed. Am I missing something here? In my controller, I have defined html2canvas functions as shown below ...

"Exploring the power of asynchronous programming with dynamic async await in

I am currently working on creating a versatile function that can dynamically call async functions. //passing the controller and functionName (string) function asyncAwaitCaller(controller, functionName) { let result = await controller[functionName]; } ...

I plan to compile a collection of names in a text field and then have the ability to select and access each name individually with just a click

I am currently working on a project that involves creating an admin site using Firebase. One of the main features of the site is large text fields that display information which can be modified. For instance, the user management page includes text fields ...

Breaking apart field values in React Final Form

In my react and redux application, I am using react final form with a 'cars' field that is a select. When the submit event is triggered, it should only return specific types like coupe: ['BMW'] instead of just the field name with values ...

Error code 400 encountered during an HTTP POST request - issue stems from incorrect design of views and serializers

I keep encountering the following error: POST http://127.0.0.1:8000/api/creator_signup/ 400 (Bad Request) Every time I try to send data from my AngularJS application to my Django backend. When making a POST request, I used the following code (): fun ...