Neatpixels
Neatpixels

Reputation: 97

Dynamic import of SVG icon components

I'm trying to import SVG icons for each item in a v-for loop, with the filename changing depending on the item's id. The icons are loading, but I get the following error for each icon imported.

Is there a better way to approach this?

Uncaught (in promise) TypeError: Failed to resolve module specifier '~/assets/img/flags/ar.svg'

<template>
<NavigationItem v-for="item in topCountries">
    <template #icon>
        <component :is="getIcon(item.id)" />
    </template>
<NavigationItem />
</template>

<script setup>
const getIcon = (id) => defineAsyncComponent(() => 
    import(`~/assets/img/flags/${id}.svg`));
</script> 

Upvotes: 0

Views: 2544

Answers (2)

Tristan
Tristan

Reputation: 421

You can have a look at https://nuxt.com/modules/nuxt-svgo module. This module allows to import SVG.

npm i --save nuxt-svgo

Add it as a module dependency in your nuxt.config file

// nuxt.config.ts
import { defineNuxtConfig } from 'nuxt'

// https://nuxt.com/docs/api/configuration/nuxt-config
export default defineNuxtConfig({
  modules: ['nuxt-svgo']
})

Import SVG icons as follow:

<script setup lang="ts">
const getIcon = (id: string) => defineAsyncComponent(() => import(`@/assets/svg/${id}.svg`));
</script>

<template>
  <div v-for="item in ['icon1', 'icon2']">
    <component :is="getIcon(item)" />
  </div>
</template>

Note that if you use Typescript, you will have to create a custom.d.ts file to fix import error

// custom.d.ts
declare module '*.svg' {
  import type { DefineComponent } from 'vue'
  const component: DefineComponent
  export default component
}

Upvotes: 2

Amini
Amini

Reputation: 1792

Us the component name instead of the component path. Also, don't forget to import SVG components and add ?inline at the end of the name.

<template>
<NavigationItem v-for="item in topCountries">
    <template #icon>
        <component :is="item.icon" />
    </template>
<NavigationItem />
</template>
<script setup>
import Eye from '~/assets/img/flags/Eye.svg?inline';
import Balls from '~/assets/img/flags/Balls.svg?inline';

const topCountries = [
  { icon: 'Eye' },
  { icon: 'Balls' }
]
</script>

Upvotes: 1

Related Questions