Failed to resolve component - vue.js

I'm trying to add Vuetify to my project following the steps described here:
https://next.vuetifyjs.com/en/getting-started/installation/#manual-steps
But I get this warning message:
[Vue warn]: Failed to resolve component: v-table
If this is a native custom element, make sure to exclude it from component resolution via compilerOptions.isCustomElement.
I share my implementation:
TestComponent.vue
<template>
<v-table>
<thead>
<tr>
<th>Name</th>
</tr>
</thead>
<tbody>
<tr v-for="app in stuff" :key="app.name">
<td>{{app.name}}</td>
</tr>
</tbody>
</v-table>
</template>
<script lang="ts">
import { Options, Vue } from 'vue-class-component';
#Options({
props: {
msg: String,
stuff: Object,
},
})
export default class Debugger extends Vue {
msg!: string;
stuff!: {name: string, id: number, [key: string]: unknown}[];
title = 'a title';
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped lang="scss">
</style>
App.vue
<template>
<nav>
<router-link to="/">Home</router-link> |
<router-link to="/about">About</router-link>
</nav>
<router-view/>
</template>
<style lang="scss">
</style>

I just forgot to add my instance of vuetify to my app:
Before
createApp(App).use(store).use(router).mount('#app');
After
createApp(App)
.use(store)
.use(router)
.use(vuetify)
.mount('#app');
main.ts
import 'vuetify/styles'
import { createVuetify } from 'vuetify'
import * as components from 'vuetify/components'
import * as directives from 'vuetify/directives'
import { createApp } from 'vue';
import App from './App.vue';
import router from './router';
import store from './store';
const vuetify = createVuetify({
components,
directives,
})
createApp(App)
.use(store)
.use(router)
.use(vuetify)
.mount('#app');

Related

How to properly register a component in a Vue 3 + Composition API app?

I'm trying to build an app with two layout, one with header and everything, one with just the background for some special pages(like login pages).
I've tried the following:
Created 2 view page:
layouts/Default.vue
<template>
<header class="flex justify-around">
<Header class="w-10/12 max-w-screen-lg"></Header>
</header>
<div class="grow h-full flex justify-around">
<div class="bg-white m-5 rounded-lg p-3 w-10/12 max-w-screen-lg shadow-lg">
<slot />
</div>
</div>
</template>
<script setup lang="ts">
import Header from "../components/Header.vue";
</script>
and
layouts/Plain.vue
<template>
<div class="grow h-full flex justify-around">
<div class="bg-white m-5 rounded-lg p-3 w-10/12 max-w-screen-lg shadow-lg">
<slot />
</div>
</div>
</template>
In my router/index.ts, I provide a "meta"
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes: [
{
path: '/',
name: 'home',
component: HomeView,
},
{
path: '/login',
name: 'login',
component: LoginView,
meta: { layout: 'plain' },
},
{
path: '/about',
name: 'about',
// route level code-splitting
// this generates a separate chunk (About.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () => import('../views/AboutView.vue'),
},
],
});
In my App.vue: I try to use this to create a component that wraps my routerView:
<script setup lang="ts">
import { computed } from "vue";
import { RouterView, useRoute } from "vue-router";
const route = useRoute();
const layout = computed(() => {
return (route.meta.layout || 'default');
});
</script>
<template>
<div id="root"
class="min-h-full bg-gradient-to-br from-indigo-500 via-purple-500 to-pink-500 flex flex-col">
<component :is="layout">
<RouterView></RouterView>
</component>
</div>
</template>
And more important, in my main.ts file, I did try to register them:
import { createPinia } from 'pinia';
import Vue, { createApp } from 'vue';
import App from './App.vue';
import router from './router';
import './assets/main.css';
import Plain from './layouts/Plain.vue';
import Default from './layouts/Default.vue';
const app = createApp(App);
app.component('default', Default);
app.component('plain', Plain)
app.use(createPinia());
app.use(router);
app.mount('#app');
But when I try to display ANY page, I get this:
Uncaught SyntaxError: The requested module '/node_modules/.vite/deps/vue.js?v=7cc2bcdd' does not provide an export named 'default' (at main.ts:2:8)
So I guess, that app.component('vue-name', component) is not the correct approach, but I can't find how?
The error is unrelated to your component registration, but rather it points to this:
👇 // The requested module 'vue.js' does not provide an export named 'default'
import Vue, { createApp } from 'vue';
In Vue 3, the vue module has no default export, so import Vue from 'vue' would fail. The Vue import also isn't used anywhere in main.ts, so you apparently don't even need it. The solution is to remove it:
import { createApp } from 'vue'; ✅
demo
According to official docs you should import them inside the App.vue and use them as variables :
<script setup lang="ts">
import { computed } from "vue";
import { RouterView, useRoute } from "vue-router";
import Plain from '../layouts/Plain.vue';
import Default from '../layouts/Default.vue';
const route = useRoute();
const layout = computed(() => {
return route.meta.layout==='plain'? Plain : Default;
});
</script>
<template>
<div id="root"
class="min-h-full bg-gradient-to-br from-indigo-500 via-purple-500 to-pink-500 flex flex-col">
<component :is="layout">
<RouterView></RouterView>
</component>
</div>
</template>
You could use normal script without setup to get globally registered components, by using vite try out vite-plugin-vue-layouts to register your layouts dynamically.

No export statement in App.vue, but App module is imported in main.ts. How is this possible?

In the example router project generated by Vue CLI, I don't see export statement in App.vue. But App module is found imported in main.ts. How the import of a module is made possible without an export statement?
But I see the export statement in App.vue of a non-router example project.
main.ts
import { createApp } from "vue";
import App from "./App.vue";
import router from "./router";
createApp(App)
.use(router)
.mount("#app");
App.vue of router example project
<template>
<div id="nav">
<router-link to="/">Home</router-link> |
<router-link to="/about">About</router-link>
</div>
<router-view />
</template>
<style>
...
</style>
App.vue of a non-router example project
<template>
<img alt="Vue logo" src="./assets/logo.png" />
<HelloWorld msg="Welcome to Your Vue.js + TypeScript App" />
</template>
<script lang="ts">
import { Options, Vue } from "vue-class-component";
import HelloWorld from "./components/HelloWorld.vue";
#Options({
components: {
HelloWorld
}
})
export default class App extends Vue {}
</script>
<style>
...
</style>

Need help figuring out why vue-router isn't working for my simple tab control scenario

I have a very simple sample app with a tab control. I'd like either component A or component B to be displayed when a tab is selected. This should be handled by vue-router fairly easily but I don't know what's wrong with my config.
When I click on either tab button, nothing happens. None of my components display.
What am I missing?
main.js
import Vue from 'vue';
import {
Tabs,
} from 'buefy';
import 'buefy/dist/buefy.css';
import App from './App.vue';
import './registerServiceWorker';
import router from './router';
import store from './store';
Vue.use(Tabs);
Vue.config.productionTip = false;
new Vue({
router,
store,
render: (h) => h(App),
}).$mount('#app');
App.vue
<template>
<div id="app">
<section>
<b-tabs type="is-toggle">
<b-tab-item label="Component A" to="/ComponentA"></b-tab-item>
<b-tab-item label="Component B" to="/ComponentB"></b-tab-item>
</b-tabs>
</section>
<router-view />
</div>
</template>
<style>
</style>
router\index.js
import Vue from 'vue';
import VueRouter from 'vue-router';
import ComponentA from '#/components/ComponentA.vue';
import ComponentB from '#/components/ComponentB.vue';
Vue.use(VueRouter);
const routes = [
{
path: '/ComponentB',
name: 'ComponentA',
component: ComponentA,
},
{
path: '/ComponentB',
name: 'ComponentB',
component: ComponentB,
},
];
const router = new VueRouter({
routes,
});
export default router;
components\ComponentA.vue
<template>
<div>Hello From Component A</div>
</template>
components\ComponentB.vue
<template>
<div>Hello From Component B</div>
</template>
I think this is an existing issue with Tabs & Router in Buefy. You could do something like this:
<b-tabs>
<router-link
label="Component A"
:to="{ name: 'ComponentA' }"
>
Component A
</router-link>
<router-link
label="Component B"
:to="{ name: 'ComponentB' }"
>
Component B
</router-link>
</b-tabs>
Or use a Buefy component that supports Vue Router, e.g:
<b-button tag="router-link" to="/ComponentA" type="is-link">
Component A
</b-button>

Use vue component in other vue component file

I tried to use a vue component(Global.vue) in other component(App.vue), but there
Failed to mount component: template or render function not defined
error.
Global.vue:
<template>
<div class="global-view">
<p>Global </p>
</div>
</template>
<script>
export default {
name: 'global'
}
</script>
App.vue:
<template>
<div id="app">
<global></global>
<router-view></router-view>
</div>
</template>
<script>
export default {
name: 'app'
}
</script>
main.js:
import Vue from 'vue'
import App from './App'
import router from './router'
Vue.component('global', require('./components/Global'))
Vue.config.productionTip = false
new Vue({
el: '#app',
router,
template: '<App/>',
components: { App }
})
You need to import the component within the component file that you want to use it in.
`import Global from './components/Global'
From there you need to add a new key inside your components option that will "register" the component.
Here is what you want your app component to look like.
<template>
<div id="app">
<global></global>
<router-view></router-view>
</div>
</template>
<script>
import Global from './components/Global
export default {
name: 'app'
components: {
'global': Global,
}
}
</script>
<global></global> should be able to render at this point.
I use import instead of require(in main.js) and it works for me:
import Global from './components/Global.vue
Vue.component('global', Global)`

Vue: Adding a sub-component into component

All my pages are created under Page-Component.vue, and I am trying to use vue-data-tables
main.js
var Vue = require('vue')
import VueRouter from 'vue-router'
import Vuex from 'vuex'
import DataTables from 'vue-data-tables'
Vue.use(Vuex)
Vue.use(VueRouter)
Vue.use(DataTables)
import App from './App.vue'
import PageContent from './components/PageContent.vue'
import MyPage from './components/MyPage.vue'
let router = new VueRouter({
// router config
}
var dataTables = DataTables.default;
Vue.component('page-content', PageContent);
let MyApp = Vue.component('app', App);
MyApp = new MyApp({
el: '#app',
router,
store
})
MyPage.vue
<template>
<page-content page-title="Supervisor Review">
<div class="main-content">
<data-tables
:data='this.pending_shots'
>
<el-table-column prop="shot_id" label="ID" sortable="custom">
</el-table-column>
<el-table-column prop="shot_name" label="Shot" sortable="custom">
</el-table-column>
<el-table-column prop="shot_description" label="Description" sortable="custom">
</el-table-column>
</data-tables>
</div>
</page-content>
</template>
<style src="semantic-ui-css/semantic.min.css" media="screen" title="no title" charset="utf-8" />
<script>
import Vue from 'vue'
export default {
data () {
return {
pending_shots: [],
}
},
created: function() {
Vue.axios.get(
'http://server:1234/path/to/api', {
headers: {
'Authorization': 'Bearer ' + localStorage.getItem('access_token')
}
})
.then(response => {
this.pending_shots = JSON.stringify(response.data)
})
.catch((error) => {
this.pending_shots = error
})
}
}
}
</script>
Errors
19:32:08.263 [Vue warn]: Unknown custom element: <el-row> - did you register the component correctly? For recursive components, make sure to provide the "name" option.
found in
---> <DataTables>
<PageContent> at src/components/PageContent.vue
<SupervisorReview> at src/components/SupervisorReview.vue
<Root> 1 6:485:7
warn webpack-internal:///6:485:7
createElm webpack-internal:///6:5099:11
createChildren webpack-internal:///6:5209:9
createElm webpack-internal:///6:5114:9
...
...
19:32:08.265 [Vue warn]: Unknown custom element: <el-col> - did you register the component correctly? For recursive components, make sure to provide the "name" option.
found in
---> <DataTables>
<PageContent> at src/components/PageContent.vue
<SupervisorReview> at src/components/SupervisorReview.vue
<Root> 1 6:485:7
warn webpack-internal:///6:485:7
createElm webpack-internal:///6:5099:11
createChildren webpack-internal:///6:5209:9
createElm webpack-internal:///6:5114:9
...
...
from the docs:
This lib depends on the following element-ui components:
el-table
el-table-column
el-row
el-col
el-input
el-button
el-pagination
el-checkbox
el-checkbox-group
So you need to import ElementUI:
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-default/index.css'
import DataTables from 'vue-data-tables'
Vue.use(ElementUI)
Vue.use(DataTables)