Vue - Using component inside other component - javascript

I am trying to use a search-bar component inside my home.vue component but I can't figure out why its not working.
Folder structure
App.vue
components
home.vue
query.vue
common
HeaderBar.vue
SideBar.vue
SearchBar.vue
App.vue
script
import HeaderBar from './components/common/HeaderBar'
import SideBar from './components/common/SideBar'
export default {
name: 'App',
components: {
HeaderBar,
SideBar
},
html
<template>
<div id="app">
<HeaderBar></HeaderBar>
<SideBar></SideBar>
<main class="view">
<router-view></router-view>
</main>
</div>
</template>
This above works just fine.
Home.vue
script
import SearchBar from './common/SearchBar'
export default {
name: 'Home',
components: SearchBar
}
html
<template>
<section class="home">
<div class="hero-content">
<h1>Hello World</h1>
<SearchBar></SearchBar>
</div>
</section>
</template>
I get those errors:
[Vue warn]: Invalid component name: "_compiled". Component names can
only contain alphanumeric characters and the hyphen, and must start
with a letter.
[Vue warn]: Invalid component name: "__file". Component names can only contain alphanumeric characters and the hyphen, and must start with a letter.
[Vue warn]: Unknown custom element: - did you register the
component correctly? For recursive components, make sure to provide
the "name" option.
found in
---> <Home> at src\components\Home.vue
<App> at src\App.vue
<Root>

By default you have to use it with kebab-case in template tag.
Register component as of PascalCase notation. Use it in component with kebab-case notation. Simple as that!
Case 1 : Default
<template>
<section class="home">
<div class="hero-content">
<h1>Hello World</h1>
<search-bar></search-bar>
</div>
</section>
</template>
<script>
import SearchBar from './common/SearchBar'
export default{
components: SearchBar
}
</script>
Case 2 : Customized
Or you want to register it with your way(by applying custom name) just change this code :
export default{
components: {
'search-bar' : SearchBar
}
}
UPDATE: This answer was provided in reference to vue version 2.x. I am unaware of vue 3.x and haven't read 3.x docs. You can always submit an edit draft for vue 3.x compatible solution. Thanks!

Script of Home.vue should be like following
import SearchBar from './common/SearchBar'
export default {
name: 'Home',
components: {
'SearchBar': SearchBar
}
}
If you SearchBar component already have a name property values SearchBar, the 'SearchBar' filed name is not required.

May or May not help you, but I did a silly mistake: as
import ServiceLineItem from "#/Pages/Booking/ServiceLineItem";
export default {
components: ServiceLineItem,
};
As it should be like :
import ServiceLineItem from "#/Pages/Booking/ServiceLineItem";
export default {
components: {
ServiceLineItem,
},
};

Related

vuejs : My vue component is not rendering

i have a vue component,but when i try to render it,its not render correctly instead shown as html tag
here is component code
view.vue
<template>
<div>
<h1>This is view component</h1>
</div>
</template>
<script>
import Vue from "vue";
export default {
name: 'view',
props: ["store"],
data:function(){
return {}
}
};
</script>
now when i try to render it like below
<div>
<b-modal ref="my-modal2" hide-footer title="Store Details" class="mt-5">
<view :store='curStore'/>
</b-modal>
</div>
it gives me this result
any suggestion on whats going wrong? thanks in advance
my app mounted using following code
new Vue({
el: '#app',
router,
template: '<App/>',
components: { App }
});
You have to import your component and add it to components as well.
Check the Vue documentation:
https://v2.vuejs.org/v2/guide/components-registration.html#Local-Registration
import ComponentA from './ComponentA.vue'
export default {
// ...
components: {
ComponentA
},
// ...
}
There are nuances for older JavaScript versions. Check the above mentioned link for details.

imported component into views not showing / VUE js

TLDR: Ive nested a component into a views folder and it wont show, I believe I have imported it correctly and think I'm missing something / any help here would be great
im importing a component into a views file which is then to be displayed via the vue router - the issue is the component or view does not show -
Oddly this code works if I ask the router to display the component as a stand alone, but not when I nest the component into the views file:
File structure is:
VIEWS FILE importing the component to be nested inside of it:
src/views/Contact.vue <<<< i imagine I have an issue here but I cannot seem to figure this out
<template>
<div class="contact_container">
<Contact/>
</div>
</template>
<script>
import Contact from '#/components/Contact.vue'
export default {
name: 'Contact',
components: {
Contact
}
}
</script>
Component file
src/components/Contact.vue
<template>
<div>
<h1>Welcome to the contact page</h1>
</div>
</template>
<script>
export default {
name: 'Contact',
data(){
return{
}
}
}
</script>
Views Router File:
src/router/index.js
import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '../views/Home.vue'
import Contact from '../views/Contact.vue'
Vue.use(VueRouter)
const routes = [
{
path: '/',
name: 'Home',
component: Home
},
{
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(/* webpackChunkName: "about" */ '../views/About.vue')
},
{
path: '/contact',
name: 'Contact',
component: Contact
}
]
const router = new VueRouter({
routes
})
export default router
and finally App.veu
<template>
<div id="app">
<div id="nav">
<router-link to="/">Home</router-link> |
<router-link to="/about">About</router-link> |
<router-link to="/contact">Contact</router-link>
</div>
<router-view/>
</div>
</template>
/// UPDATED ///
In the code below - what does the name property do? 
(the code below is defining a component) 
<template>
    <div>
        <h1>Welcome to the contact page</h1>
    </div>
</template>
<script>
export default {
    name: 'Contact-Component', <<<< what does this do? 
    data(){
        return{
        }
    }
}
</script>
The reason why i'm a little lost here is because when we use this component we import it into another file using the below: 
import Contact from '../views/Contact.vue'
In that process we have defined the component as Contact (so it is not referenced by its name any more) .... so why did we define a name?
If there is any documentation on this that would be amazing and while it seems like a silly question (and probably is) it is distracting me with curiosity...
Thanks for any help -
Wally
change your code with this
<template>
<div class="contact_container">
<Contact/>
</div>
</template>
<script>
import Contact from './components/Contact.vue'
export default {
name: 'Contact',
components: {
"Contact":contact
}
}
</script>
The name is used to allow the component to recursively invoke itself in its template. It also helps when debugging as it allows for a more helpful error message.
Have a read over this to get a better idea: https://v2.vuejs.org/v2/api/#name
You have to let the app know it's a Vue component:
<script lang="js">
import Vue from 'vue';
export default Vue.extend({
name: 'Contact',
...
});

Vue.js with TypeScript getting data from Twig error Property does not exist

I'm having trouble printing out the data from Twig template on my Symfony app. I am using Vue.js with TypeScript enabled.
main.ts:
import HeaderNav from './components/HeaderNav.vue'
new HeaderNav({el: '.headnav'});
HeaderNav.vue:
<template>
<div class="headnav headnav-fixed z-depth-1">
{{test}}
</div>
</template>
<script lang="ts">
import Vue from 'vue';
import { Component, Emit, Prop, Watch } from 'vue-property-decorator';
#Component({
props: {
test: {
type: String,
default: "{}"
}
},
mounted: function () {
console.log(this.test);
}
})
export default class HeaderNav extends Vue {}
</script>
header.html.twig:
<div class="headnav" data-test="hello"></div>
I get this error while compiling:
Property 'test' does not exist on type 'Vue'.
Any ideas that am I doing wrong? I am thinking that calling the component HeaderNav first might be the problem, because it instantly overrides the element with class 'headnav', but I am trying to create the components only for separate elements on my site, I don't want to put whole application into Vue.js.
I hope the problem is with you defined props.
In Vue with typescript you need to use props like this:
import { Component, Prop, Vue } from 'vue-property-decorator';
#Component({
name: "HeaderNav"
})
export default class HeaderNav extends Vue {
#Prop({ default: '' }) test!: string;
created(){
console.log(this.test)
}
}
I hope this will help you.
For more information checkout this article: https://blog.logrocket.com/how-to-write-a-vue-js-app-completely-in-typescript/

How to register component in vue+ts correctly?

I have this code:
App.vue
<template>
<v-container>
<div>
<schedule-table
v-if = "schedule.length > 0"
:exercises="schedule[0].exercises"
/>
</div>
</v-container>
</template>
<script lang="ts">
import Vue from "vue";
import { Component } from "vue-property-decorator";
import ScheduleTable from '#/components/ScheduleTable.vue'
#Component({
components: {
ScheduleTable,
}
})
</script>
ScheduleTable.vue
<template>
<v-container>
<schedule-week
:exercises="exercises"
/>
</v-container>
</template>
<script lang="ts">
import Vue from "vue";
import { Component, Prop } from "vue-property-decorator";
import { IExercise } from "#/interfaces"
import ScheduleWeek from '#/components/ScheduleWeek.vue'
#Component({
name: 'ScheduleWeek',
components: {
ScheduleWeek,
}
})
#Component
export default class ScheduleTable extends Vue {
#Prop( {required: true, type: Array } ) readonly exercises!: IExercise;
}
</script>
ScheduleWeek.vue
<template>
<v-container
:ex="exercises"
>
here is tables (but this tables dosn't show and any other text dosn't show)
</v-container>
</template>
<script lang="ts">
import Vue from "vue";
import { Component, Prop } from "vue-property-decorator";
import { IExercise } from "#/interfaces"
#Component
export default class ScheduleWeek extends Vue {
#Prop( {required: true, type: Array } ) readonly exercises!: IExercise;
}
</script>
And have vue warn:
Unknown custom element: < schedule-week > - did you register the
component correctly? For recursive components, make sure to provide
the "name" option.
How to fix this problem? How to register component correctly?
There are multiple ways to declare a vue-component when you use typescript. The class-based SFC approach (the one you are using) needs to follow a slightly different syntax. You used the typescript decorator twice in your schedule-week component
App.vue
<v-container>
<div>
<schedule-table
v-if = "schedule.length > 0"
:exercises="schedule[0].exercises"
/>
</div>
</v-container>
</template>
<script lang="ts">
import { Component, Vue } from "vue-property-decorator"; // you can import vue here
import ScheduleTable from '#/components/ScheduleTable.vue'
#Component({
components: {
ScheduleTable,
}
})
export default class App extends Vue {} // the #Component() decorator needs to be followed by the exported class
Correspondingly your other components:
ScheduleTable.vue
<template>
<v-container>
<schedule-week
:exercises="exercises"
/>
</v-container>
</template>
<script lang="ts">
import { Component, Vue, Prop } from "vue-property-decorator"; // see above
import { IExercise } from "#/interfaces"
import ScheduleWeek from '#/components/ScheduleWeek.vue'
#Component({
name: 'ScheduleTable',
components: {
ScheduleWeek,
}
}) // >>>don't use the decorator twice<<<
export default class ScheduleTable extends Vue {
#Prop( {required: true, type: Array } ) readonly exercises!: IExercise;
}
</script>
ScheduleWeek.vue
<template>
<v-container
:ex="exercises"
>
here is tables (but this tables dosn't show and any other text dosn't show)
</v-container>
</template>
<script lang="ts">
import { Component, Vue, Prop } from "vue-property-decorator"; // see above
import { IExercise } from "#/interfaces"
#Component
export default class ScheduleWeek extends Vue {
#Prop( {required: true, type: Array } ) readonly exercises!: IExercise;
}
</script>
##EDIT:
From the officiel TypeScript Documentation:
With the introduction of Classes in TypeScript and ES6, there now exist certain scenarios that require additional features to support annotating or modifying classes and class members. Decorators provide a way to add both annotations and a meta-programming syntax for class declarations and members.
Decorators are basically TypeScript(JavaScript) functions which are used to add additional information to the following class (your component) or class members. This also means a decorator cannot stand alone. The #Component() decorator takes an Object as parameter which is 'as-is' translated into component-options.
TL;DR
To register the components SubOne and SubTwo in MyComponent, pass it to the #Component decorator:
import { Component, Vue } from "vue-property-decorator";
#Component({
components: {
SubOne,
SubTwo,
}
})
export default class MyComponent extends Vue {
…
}
And make sure you also decorate the SubComponents like so;
import { Component, Vue } from "vue-property-decorator";
#Component
export default class SubOne extends Vue {
…
}
Error in #MarcRo's answer
Setup and resulting Error
In the Component ScheduleTable.vue, the decorator #Component gets the parameter name set to the Component it is about to import. This leads to a recursive call of said Component and hence an Error.
Fix
Set name: 'ScheduleTable' - or even drop it. The class name seems to be used (which is what we are doing).
Aside
I could not find a doc on what can actually passed to the decorator, but it's used like this in #MarcRo's answer in App.vue as well as here. (The link in the comments there seems to be old).
I don't have enought reputation to comment and a fixing edit got rejected, so sorry for the extra post.
Thank you #MarcRo for teaching me how to use this and the facepalm moment after solving the recursion error after a way too long time ;)

How to use VueJS 2 global components inside single file components?

I am trying to use a globally registered component (with Vue.component) inside a single file component but I am always getting
vue.common.js:2611[Vue warn]: Unknown custom element: <my-component> - did you register the component correctly?
For example:
main.js:
...
Vue.component('my-component', {
name: 'my-component',
template: '<div>A custom component!</div>'
})
...
home.vue:
<template>
<div>
<my-component></my-component>
</div>
</template>
<script>
module.exports = {
name: 'home'
}
</script>
If I register it locally, it works OK:
<template>
<div>
<my-component></my-component>
</div>
</template>
<script>
module.exports = {
name: 'home',
components: {
'my-component': require('./my-component.vue')
}
}
</script>
You don't need the module.exports. You can register the component globally by having this within the mycomponent.vue file.
<template>
<div>A custom component!</div>
</template>
<script>
export default {}
</script>
Then add to main.js
import MyComponent from './component.vue'
Vue.component('my-component', MyComponent);
or I typically register them in a 'globals' file them import that into the main.
That should then allow you to use my-component anywhere in the app.
Component.vue
<template><div>A custom component!</div></template>
<script>export default { code here... }</script>
Use this component in home.vue:
<template>
<div>
<my-component></my-component>
</div>
</template>
<script>
import component from './component.vue'
export default {
components: { my-component: component }
}
</script>

Categories