Vue - How to import components dynamically - vue.js

So I will have an array for X length. I have no clue how many components will be included. How do I import them, can I loop over the array and import them, or use v-bind:is?
Any help is welcome!
Thanks,
Justin.
<template>
<div id="app">
<component v-for="(componentName, index) in this.components" v-bind:is="componentName" />
</div>
</template>
<script>
import Vue from 'vue'
export default {
name: 'app',
// Import just the ones I need
}
</script>

You can include an i when you have no idea how many will be included
<component v-for="i in this.components" v-bind:is="componentName" />
</div>
then for the js
export default {
name: 'app',
data: function() {
return {
this: {id: 1, name: ''}
}
}

Related

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>
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
}
calls each icon from the data. uses font awesome icons. you can also add svgs between the i tags
<template>
<ul>
<!-- list rendering -->
<li v-for="item in items">
<span class="icon">
<i :class="[faClass(item.icon)]"
aria-hidden="true"></i>
</span>
</li>
</ul>
</template>
<script>
export default {
name: "navbarMobile",
data() {
return {
//listItems
items: [
{
icon: 'home',
},
{
icon: 'wrench',
},
{
icon: 'project-diagram',
},
{
icon: 'cogs',
},
{
icon: 'phone',
}
]
}
},
methods: {
faClass(icon) {
return `fa fa-${icon}`;
}
}
}
</script>
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>

Can't resolve component import VueJS

I'm trying to use MainNavbarButton within MainNavbar. I imported the component, but get the error of "Module not found: Error: Can't resolve './components/MainNavbarButton.vue'" All the solutions I found seem to stem from a spelling mistake, but I'm pretty sure that's not the case here.
MainNavbar.vue
<template>
<div id="navbar">
<MainNavbarButton />
</div>
</template>
<script>
import MainNavbarButton from './components/MainNavbarButton.vue'
export default {
name: 'MainNavbar',
components: {
MainNavbarButton
}
}
</script>
MainNavbarButton.vue
<template>
<h2>{{ title }}</h2>
</template>
<script>
export default {
name: 'MainNavbarButton',
props: {
title
}
};
</script>
App.vue
<template>
<MainNavbar/>
</template>
<script>
import MainNavbar from './components/MainNavbar.vue'
export default {
name: 'App',
components: {
MainNavbar
}
}
</script>

Vuejs import component in another component

I created a dashboard.vue component and I imported table.vue component into it but the table.vue doesn't appear in my web page and in the vue.dev tools.
When I import the table.vue in app.vue there's no issue.
Below my files.
Thanks in advance!
//dashboard.vue
<template>
<div>
<table></table>
</div>
</template>
<script>
import table from "./table";
export default {
name: 'Dashboard',
component: {
table,
}
}
</script>
<style >
</style>
//table.vue
<template>
<div>
<p>Test</p>
</div>
</template>
<script>
export default {
name: 'Table',
}
</script>
You cannot name components the same as reserved HTML elements. Change it to my-table.
You'll need to map it:
components: {
'my-table': table,
}

Vue.js "export 'Filelist' was not found in '#/components/Filelist'

I'm facing an issue with my first Vue Project. I already googled for a while but can't find something very usefull.
I simply try to create a parent ("Files") and a child component ("Filelist") and use the Filelist in Files. This is not working as expected. I can't see the mistake, beacause i already added
export default {
name: 'Filelist',
The only hint I can get is from the browser console
[Vue warn]: Unknown custom element: <Filelist> - did you register the component correctly? For recursive components, make sure to provide the "name" option.
found in
---> <Files> at src/docs/categories/Files.vue
<App> at src/App.vue
<Root>
and
./src/App.vue (./node_modules/babel-loader/lib!./node_modules/vue-loader/lib/selector.js?type=script&index=0!./src/App.vue) 42:14-22"
export 'Filelist' was not found in '#/components/Filelist'
Thanks a lot in advance
The code of Files:
<template>
<div class="">
<h1>Hedajo</h1>
<Filelist :msg="sometext"/>
{{ sometext }}
</div>
</template>
<script>
import { Filelist } from "#/components/Filelist.vue";
export default {
name: "Files",
components: {
Filelist
},
data() {
return {
sometext: "hejo",
};
},
methods: {
}
};
</script>
<style scoped>
</style>
The code of Filelist:
<template>
<component class="">
{{ msg }}
<p>hewhwe</p>
{{ hedadi }}
{{ testi }}
</component>
</template>
<script>
export default {
name: 'Filelist',
props: ["msg"],
data () {
return {
testi: "hedadi",
};
}
};
</script>
<style scoped>
</style>
It's a default export, so you don't need to extract it. Try
import Filelist from "#/components/Filelist.vue";
You will need to register FileList as a component before using it.
<template>
<div class="">
<h1>Hedajo</h1>
<Filelist :msg="sometext"/>
{{ sometext }}
</div>
</template>
<script>
import Vue from 'vue';
Vue.component('Filelist', require('#/components/Filelist.vue').default);
....
You dont need the import Filelist statement in this case

Vue-cli change object value globally

I have this code in file app.vue :
<template>
<div id="app">
<button v-on:click="component = 'login'">aa</button>
<component v-bind:is="component"></component>
</div>
</template>
<script>
import acceuil from './components/acceuil.vue'
import login from './components/login.vue'
export default {
name: 'app',
components: {
acceuil,
login
},
data(){
return {
component: 'acceuil'
}
}
}
</script>
How can I toggle between acceuil/login in component from a different vue file ?
You need to pass the imported dependency (the object or the name of the component as a string) to v-bind:is. You can do this by returning it in a computed function and pass it to a computed property, which you then can use in the template.
<template>
<div id="app">
<button v-on:click="isLogin = true">Show Login</button>
<component v-bind:is="currentComponent"></component>
</div>
</template>
<script>
import acceuil from './components/acceuil.vue';
import login from './components/login.vue';
export default {
name: 'app',
data () {
return {
isLogin: false
};
},
computed: {
currentComponent () {
return this.isLogin ? login : acceuil;
}
},
};
</script>
See also the documentation of dynamic components in the official docs.