Is it possible to dynamically import a Vue.js component based on a prop value?

Currently, I am utilizing the Material design Icons library specifically made for Vue.js. In this library, each icon is a standalone file component within its designated folder.

Within my project, I have a separate component called ToolbarButton, which includes a prop named Icon. What I aim to achieve is importing a component with a name that matches the passed prop.

Below is a snippet of my code:

<template>
    <button>
        <MyIcon></MyIcon>
    </button>
</template>

<script>

import MyIcon from `icons/${icon}.vue`
export default {
    name: 'ToolbarButton',
    props: ['icon'],
    components: {
        MyIcon
    }
}
</script>

Unfortunately, this code results in a Parsing error: Unexpected token `. Even when using 'icons/' + icon + '.vue', the issue persists. Have I missed something? I have spent significant time looking for a solution but to no avail.

One suggestion I received was to import all of the components, as the unused ones will be eliminated during compilation. However, this doesn't feel like the most efficient approach. Are there any other suggestions or solutions that I could explore?

Answer №1

If you want to implement async components, you can do so by following this example:

<template>
  <MyIcon />
</template>

<script setup>
import { defineAsyncComponent } from "vue";

const props = defineProps(["icon"]);
const MyIcon = defineAsyncComponent(function () {
  return import(`./icons/Icon${props.icon}.vue`);
});
</script>

Answer №2

  1. One potential option is utilizing the backticks symbol (`). In JavaScript, backticks serve to delimit template literals, which facilitate simpler string interpolation and multi-line strings. Nonetheless, it's worth noting that template literals may not be fully compatible across all browser types and JavaScript versions.

import MyIcon from `icons/${icon}.vue` // misguided - employs backticks
import MyIcon from 'icons/' + icon + '.vue' // misguided - involves concatenation
import MyIcon from 'icons/' + icon // accurate - entails concatenation with file extension
import MyIcon from `icons/${icon}` // accurate - utilizes template literals with curly braces
import MyIcon from `icons/${icon}.vue`.default // accurate - incorporates template literals with curly braces and .default

  1. Another suggestion is to consider dynamic importing. This method optimizes the process and aids in reducing bundle size.

export default {
  name: 'ToolbarButton',
  props: ['icon'],
  components: {
    MyIcon: () => import(`icons/${this.icon}.vue`)
  }
}

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

Leverage a JavaScript plugin from the node modules directory within your Vue.js project

Is there a way to import Cal-HeatMap (https://www.npmjs.com/package/cal-heatmap) into my project after saving it with npm install? This is the method I attempted: <script> import calHeatmap from 'cal-heatmap' export default { na ...

TypeScript throws an error if trying to access an Object variable using a String

While the code below is functioning as intended, I am encountering an error in the VS Code Typescript compiler stating that "Type 'String' cannot be used as an index type". Oddly enough, using a string literal instead of a variable like ...

Issues with Ajax response being added to the table

I am encountering a technical problem with my university project. The task assigned by the professor is as follows: We need to create a static table that lists 3 domain names in order to enhance the performance of the domain availability API. <table&g ...

Box Filter Plugin

Can anyone please help me identify the name of the plug-in used for the perfect filter box on this website I found? Website address: ...

Scope of MongoDB's `.findOne` method

Having trouble with variable scope. var max; ClassModel.findOne({ class: '1a' }, function (err, class1a) { if (err) return handleError(err); max = class1a.members; console.log(max); }); console.log(max); Why does ...

Why does the Next.js GET index request keep fetching multiple times instead of just once?

Currently, I am encountering an issue while working on a tutorial app with Next.js. One of my components is not rendering due to what seems like multiple executions of a simple GET request for an index page. The problem perplexes me, and I need some assist ...

The Bootstrap validator triggers the form submission only after the second click

When I click on the submit button, I am attempting to submit a form that has its default action prevented and first checks a condition before proceeding. Below is the code snippet: $('#payment-form').bootstrapValidator({ live: 'dis ...

What is the method for adding line breaks to a JSON file?

I've been developing a Discord bot and I'm currently storing currency values in a json file. The functionality is working smoothly, but the issue I'm facing is that it's adding them to the json file in a single line which makes it diffi ...

Adjust the size and position of the text input field

I'm struggling to find a way to both resize and move the box without one action interfering with the other. Whenever I attempt to change the size of the box, it triggers the move event at the same time. Clicking on the box should make it resizable, bu ...

Use JavaScript to identify and color the intersecting area of two triangles that overlap on a webpage

I created two triangular divs using HTML and I am utilizing jQuery UI to enable them to be draggable. Now, my goal is to overlap these two triangles and change the color of the overlapping area to a different shade. Here is an example: https://i.sstatic. ...

Reading data from a Node PassThrough stream after writing has finished can be achieved by piping the stream

Is it possible to write to a Node Passthrough stream and then read the data at a later time? I am encountering an issue where my code hangs when trying to do this. Below is a simplified example in Typescript: const stream = new PassThrough(); strea ...

Populate the div with the URL parameter only when another span element is empty after a specified time interval using setTimeout

When displaying a person's name on a page, there are two different methods to consider. It can be extracted from the URL or retrieved from an email form in the CMS used. However, these two approaches sometimes conflict with each other. Currently, I h ...

Managing various iterations of identical repositories

Currently in the process of constructing a library of unique react components that are being utilized in various downstream applications. To incorporate these components into my downstream applications, I rely on the package.json. Recently, I began ponde ...

Error: Material UI search bar doesn't refresh interface

I implemented Material UI's auto complete component to create a dynamic select input that can be searched. The component is fed options in the form of an array consisting of strings representing all possible choices. <Grid item xs = {props.xs} cla ...

What steps can I take to stop Vetur and TypeScript from displaying duplicate TypeScript warnings in VSCode?

I have a Vue2 project using TypeScript in VSCode with Vetur and TypeScript extensions installed. Whenever there is a TypeScript warning, both the TypeScript and Vetur overlays show duplicate warnings. Example of duplicate warnings Also, the intellisense ...

What is preventing Foundation 5 from initializing JavaScript components properly?

I am in the process of upgrading a website that is built with Foundation to version 5.2.0 in order to address some Orbit issues and other improvements. I typically initialize components using data attributes like data-orbit and have had success with using ...

I am having trouble getting the unix timestamp to work with Meteor's API, pickadate.js

Based on the information from the API at , I have implemented the following code to retrieve a Unix timestamp based on a selected date. Initially, I configured: $('.startDate').pickadate({ selectMonths: true, selectYears: 15 ...

Protractor can now successfully locate and interact with a nested button element

I am trying to click on the second button, but I can't differentiate between the two buttons using class names. div class="ng-view ff-domain ng-scope"> <div class="hero-unit blur-background ng-scope"> <h1></h1> <h2> ...

What is the best way to export my mongo schema to a file and then utilize it for inserting data?

I've been encountering difficulty when attempting to insert data into my collection. I'm not entirely sure if I'm doing it correctly, so I apologize for the vague request. Hopefully, by providing you with my code, you can help me understand ...

Increase the width of the div to extend it to the right side of the

After analyzing the issue, it seems like the solution lies in extending the wrapper div to the right side of the page without any wrapping. Whenever I attempt to set the width to 100vw or 100%, the content within the div gets pushed below all the other ele ...