I'm trying to create a component out of my app's <v-navigation-drawer>, and I'm seeing an error:
Unknown custom element: <app-navigation-drawer> - did you register the component correctly? For recursive components, make sure to provide the "name" option.
Being new to vue.js, I've figured out components to be used within a specific route, but can't figure out using a custom component in the main App.vue file.
I've tried importing and adding it as a component in the Vue instance, I've also tried importing it within App.vue and exporting a default component with that as a component.
Q: Can someone please help me understand where I would need to register this component, or what I'm doing wrong?
App.vue
<template>
<div id="app">
<v-app>
<app-navigation-drawer/>
</v-toolbar>
<v-content>
<v-container class="grey lighten-5" fluid="fluid" fill-height="fill-height">
<router-view></router-view>
</v-container>
</v-content>
</v-app>
</div>
</template>
main.js
import Vue from 'vue';
import App from './App.vue';
import router from './router';
import store from './store';
import Vuetify from 'vuetify';
import NavigationDrawer from './views/NavigationDrawer.vue';
Vue.use(Vuetify);
new Vue({
router,
store,
components: { NavigationDrawer },
render: h => h(App)
}).$mount('#app');
NavigationDrawer.vue
<template>
<v-navigation-drawer app stateless value="true">Drawer</v-navigation-drawer>
</template>
<script>
export default {
name: 'app-navigation-drawer'
}
</script>
It is recomended you declare your component like this:
components: { 'app-navigation-drawer': NavigationDrawer }
That should work.
If you want to do it directly, use the name as declared:
<NavigationDrawer></NavigationDrawer>
Reference: https://v2.vuejs.org/v2/guide/components-registration.html
Related
Some of our components use other components as property.
A trivial example: <my-interface-component :popup="myPopup"/>
Where myPopup will be a component with a open method that allows to open this external popup component with a message.
In Vue 2 we used to set this property like this:
/**
* #prop {Vue} popup A root popup component to use
*/
popup: {
type: Vue
},
And we could give either a component definition or an existing component reference.
But in Vue 3 there is no more such Vue object. Should I just use Object or is there a more explicit way?
We use the CDN version of Vue 3 with Vanilla JS.
Many thanks
The right type of a component is ComponentOptions|ComponentOptions['setup'] which are simplified for readability as mentioned here:
import {ComponentOptions, PropType } from 'vue'
props:{
popup: {
type: Object as PropType<ComponentOptions|ComponentOptions['setup']>
},
}
However it's recommended to pass components/elements as slots not as props :
Child component :
<template>
<div>
<slot name="popup" />
</div>
</template>
In parent :
<template>
<div>
<template #popup>
<MyPopup />
</template>
</div>
</template>
I am very new to Vue.js and I am trying to figure out a few things about it. One of the things I would like to use it for is to implement components without creating an SPA. So in other words I can make a reference to components in a static page with out having to have it run through App component.
When I have done this with react js I have used react habitat. I am wondering if there is something similar for Vue.js that is available or is it something you can do with out a third party module-tool.
You don't need any App component. Just assign any wrapper (div) to a Vue module (Vue instance). I use a component for retrieving contacts, for example.
You can have multiple Vue applications in one page. They just cannot overlap.
html:
<div class="col-md-4 col-sm-4" id="safeContactsFooter">
..some html stuff
<ul class="phone">
<li>Phone: <safe-contact type="phone" ></safe-contact></li>
</ul>
</div>
Vue module:
export default new Vue({
el: '#safeContactsFooter',
components : {
'safe-contact' : () => import('./components/Safe contact') ,
},
});
Then, you have to register the module only when the div with the proper ID is present. Otherwise, the console will yell at you that the object doesn't exist. I do it this way:
if(document.getElementById("safeContactsFooter")){
import('../Safe contacts/Safe contacts footer.Module.js');
}
You can do that by importing your components into a JavaScript file and creating a vue instance with a referenced element:
// JS File
import Vue from 'vue';
import YourComponent from './YourComponent.vue';
export default new Vue({
el: '#app',
components: {
YourComponent
}
});
// HTML file
<div id="app">
<your-component></your-component>
</div>
I want to display different Vue component for the mobile device. And I found this solution (https://stackoverflow.com/a/48515205/11079653) via mixin.
And, for example, I have the component - Card.vue. But for the mobile device, I have created CardMovile.Vue.
Now I want to put these components in the folder Card which will contain index.js
-Card
--Card.vue
--CardMobile.vue
--index.js
After that, I just want import Card in my App.vue and index.js should decide what component needed (Card.vue or Card.mobile.vue)
<template>
<Card></Card>
</template>
<script>
import Card from './Card'
</script>
is it possible?
You could try to write the following in the Card/index.js file:
import isMobile from 'is-mobile'
import Card from './Card.vue'
import CardMobile from './CardMobile.vue'
export default isMobile() ? CardMobile : Card
Have a problem with registering component locally in Vue.js app.
I'm trying to use MovieCard.vue inside it's parent MainView.vue.
Made everythig as in the Vue docs, but still getting this error:
[Vue warn]: Unknown custom element: <movie-card> - did you register the component correctly? For recursive components, make sure to provide the "name" option.
found in
---> <MainView> at src\components\MainView.vue
<VApp>
<App> at src\App.vue
<Root>
Here goes the code for MovieCard.vue(child component)
<template>
<div>
<!-- <v-card class="movie-card" height="30vh" hover>
<v-card-media :src="'http://image.tmdb.org/t/p/w500' + movie-info.poster_path" height="100%">
<v-card class="movie-card__info-cover" width="100%" height="100%">
{{this.movie-info}}
</v-card>
</v-card-media>
</v-card> -->
</div>
</template>
<script>
export default {
name: "MovieCard",
props: ["movie-info"],
data() {
return {
visible: false
}
},
created() {
console.log("Info:", this["movie-info"])
}
}
</script>
<style>
</style>
And for MainView.vue(parent component):
<template>
<v-container class="main-view" column>
<v-btn color="pink" dark small absolute bottom left fab></v-btn>
<v-tabs centered grow color="pink" slot="extension" slider-color="yellow">
<v-tab class="main-view__option" #click="setCategory('popular')">
Popular
</v-tab>
<v-tab class="main-view__option" #click="setCategory('upcoming')">
Upcoming
</v-tab>
<v-tab class="main-view__option" #click="setCategory('topRated')">
Top Rated
</v-tab>
</v-tabs>
<v-container class="movie-cards__container" fluid grid-list-xl>
<v-layout row wrap>
<v-flex xs3 md2 class="" v-for="n in this.movies.movieLists.list" :key="n.id">
<movie-card :movie-info="n"></movie-card>
</v-flex>
<infinite-loading #infinite="infiniteHandler" spinner="spiral"></infinite-loading>
</v-layout>
</v-container>
</v-container>
</template>
<script>
import { mapState, mapActions, mapMutations } from 'vuex';
import InfiniteLoading from 'vue-infinite-loading';
import MovieCard from "./MovieCard"
console.log(MovieCard)
export default {
name: 'MainView',
components: {MovieCard},
data () {
return {
chosenCategory: 'popular'
}
},
computed: {
...mapState([
'movies'
])
},
methods: {
...mapActions([
"getNextPageByCategory",
'setCategory'
]),
async infiniteHandler($state) {
await this.getNextPageByCategory(this.chosenCategory);
$state.loaded();
console.log("yay");
},
...mapMutations([])
},
components: {
InfiniteLoading
}
}
</script>
Also, I've noticed the fact that if i put the same component into my App.vue root component, it works as intended(like any other subcomponents, which are registered locally inside App.vue(for example MainView.vue)).
In addition, I'll say that i'm using Vuex and Vuetify inside my app.
Tried to solve this issue for hours, but for now no results...
Thank you in advance for your help!
try to define your component in MainView like this :
components: {
'movie-card': MovieCard
}
edit: maybe it's because you define your components twice
In the OP question, he made the mistake defining components twice in MainView.vue, so that the latter components overrode the first one, which is the one declared movie-card component, so only
components: {
InfiniteLoading
}
is the valid registered component at the end of the day,
components: {MovieCard},
was overridden
And today, I've gone through the same shit
Unknown custom element: <movie-card> - did you register the component correctly? For recursive components, make sure to provide the "name" option.
And the mistake of mine was I mistyped the word components to component without the s. So if any of you guys go later and about to see this kind of error, chances you've mistyped something.
The Vue error prompt was also smart enough to ask us did you register the component correctly?, yet we made the assumption that we did, but hold on, we likely didn't.
That being said, the problem had nothing to do with
components: {
'movie-card': MovieCard
}
// the above is the same at the below in Vue
components: {
MovieCard
}
If you read Sovalina's answer, please notice that the answer is his edit
Another thing btw, I've thought the problem had something to do with recursive components, so I made sure providing the "name" option, but as you could read this, it didn't have a thing to do with "name" option cause movie-card was not a recursive component. In my case, I resolved my problem by adding a character s, not any name.
I'm new to this framework and I was wondering whether or not there's a component binding that allows you to specify the component to be used on a regular HTML element and not a custom one.
Let's say we have a Message component. Would it be possible to use it as:
<div component="message"></div>
instead of
<message></message>
Knockout.js supports this for their components: The "component" binding.
Yep! You can use the as-element custom attribute to do this.
Here's an example: https://gist.run?id=5fc98df81dff7eec2868ea918f6342fb
app.html
<template>
<require from="./message"></require>
<message say="Say"></message>
<div as-element="message" say.bind="what"></div>
</template>
app.js
export class App {
what = 'What!'
}
message.html
<template>
<h1>${say}</h1>
</template>
message.js
import {bindable} from 'aurelia-framework';
export class MessageCustomElement {
#bindable say = '';
}
rendered