Vue.js Component doesn't appear when embedded in another component - javascript

I have a header, logo, menu, and menu item.
The menu item contains the text "This is a menu item", but vue is not processing and displaying it.
These are the components:
App.vue
<template>
<div id="app">
<mainHeader />
</div>
</template>
<script>
import mainHeader from './components/mainHeader.vue'
export default {
name: 'App',
components: {
mainHeader
}
}
</script>
<style>
html,body{
box-sizing: border-box;
margin:0px;
padding:0px;
}
#app{
background-color:gray;
}
</style>
./components/mainHeader.vue
<template>
<div id="main-header">
<logo />
<mainMenu />
</div>
</template>
<script>
import logo from "./logo.vue";
import mainMenu from "./mainMenu.vue";
export default
{
name: 'mainHeader',
components:
{
logo,
mainMenu,
}
}
</script>
./components/mainMenu.vue
<template>
<div id="main-menu">
<menuItem />
</div>
</template>
<script>
import menuItem from "./menuItem.vue";
export default
{
name: "mainMenu",
components:
[
menuItem
]
}
</script>
./components/menuItem.vue
<template>
<div class="menu-item">
This is a menu item
</div>
</template>
<script>
export default
{
name: "menuItem"
}
</script>
When I check the DOM, the menuItem is not being parsed into a div with the message:
<div id="app">
<div data-v-ea6a1e94="" id="main-header">
<div data-v-4b16403b="" data-v-ea6a1e94="" id="logo"></div>
<div data-v-d2968a70="" data-v-ea6a1e94="" id="main-menu">
<menuitem data-v-d2968a70=""></menuitem>
</div>
</div>
</div>
How can I get the component to work?

The components option has an object as a value :
components:{
menuItem
}
it's recommended to name the component using kebab-case:
name: "menu-item"
and the file name with CamelCase MenuItem
and import it like :
import MenuItem from "./MenuItem.vue";
then register it like :
components:{
MenuItem
}
finally use it like <menu-item ... />

Related

Why do these Vue props fail outside the main component?

I am working on a Vue 3 app. I have run into a problem working with a <Navbar /> component and one of its sub-components.
In App.vue:
<template>
<Navbar />
<Content title="Home" />
<Footer />
</template>
<script>
import Navbar from './components/Navbar.vue'
import Content from './components/Content.vue'
import Footer from './components/Footer.vue'
export default {
name: 'App',
components: {
Navbar,
Content,
Footer
}
}
</script>
Within the Content.vue component, I can display the title this way:
<h1>{{ title }}</h1>
<script>
export default {
name: 'Content',
props: {
title: String
}
}
</script>
But displaying buttons with their labels by the same pattern as above does not work:
// Button.vue component
<template>
<button class="btn btn-sm btn-generate">
{{ label }}
</button>
</template>
<script>
export default {
name: 'Button',
props: {
label: String
}
}
</script>
// Navbar.vue component
<template>
<div class="navbar">
<Button label="Button 1" />
<Button label="Button 2" />
</div>
</template>
<script>
import Button from './Button'
export default {
name: 'Navbar',
components: {
Button
}
}
</script>
The problem
As a result of the code above, inside <div class="navbar"> there is only one button with no label, instead of 2 buttons labeled "Button 1" and "Button 2".
Where is my mistake?
I think that naming your component just as the already existing HTML element is not a good idea. Try changing it to MyButton and use <my-button>... in the navbar component (you still want to use <button> in MyButton, as you want to build upon it).
Most probably browser still picks just a default button instead of yours.
The first essential rule mentioned in Vue docs is Use multi-word component names.
You need to bind them so :label="button 1"

Vue: navigation component is not displayed but seen in Vue extension

I am using Vue after a long pause so sorry in advance for rather silly question.
I have a navigation component which is nested in layout component. The problem is that it is not visible on the page and in DevTools but I can see it in my Vue Chrome extension.
I feel like I am missing something really small but can't figure this out. Please help.
This my App.vue
<template>
<div id="app">
<router-view />
</div>
</template>
This is my Home page:
<template>
<Layout>
<h1>Home page</h1>
</Layout>
</template>
<script>
import Layout from '../layouts/Layout.vue';
export default {
name: 'home',
components: { Layout },
};
</script>
This is Layout component:
<template>
<div class="main">
<Navigation />
<slot />
</div>
</template>
<script>
import Navigation from '../components/Navigation.vue';
export default {
name: 'Layout',
components: { Navigation },
};
</script>
Everything is visible from Layout component except Navigation component. Here it is:
<template>
<div class="navigation">
<router-link :to="{ name: 'home' }">
Home
</router-link>
<nav>
<!-- Nav routes -->
</nav>
</div>
</template>
<script>
export default {
name: 'Navigation',
};
</script>

How to trigger a method in Single File Component from another Single File Component VueJS

I have Three components I want to trigger the show() method that is located in overlay.vue component, from the about.vue component
I am a beginner so I wish if I found some help from you guys
first is overlay.vue
<template>
<div class="overlay"></div>
</template>
<script>
export default {
name: "overlay",
methods: {
show() {
document.querySelector(".overlay").style.display = "block";
}
}
};
</script>
second is about.vue
<template>
<section class="about">
<div class="container">
<div class="row video">
<div class="col-lg-6 order-lg-1 order-2">
<img
class="dots img-fluid"
src="../assets/images/dots.svg"
alt="dots"
/>
<div class="video-wrapper">
<div class="video-img">
<img
class="img-fluid"
src="../assets/images/video.png"
alt="#"
/>
</div>
<div class="video-i">
<!-- ***************************************************************
***** this is where i want to trigger the method using this below a tag*****
*************************************************** -->
<i class="fas fa-play"></i>
</div>
</div>
</div>
</div>
</div>
</section>
</template>
The third which is the parent app.vue where I import about.vue and overlay.vue
<template>
<div id="app">
<overlay></overlay>
<about></about>
</div>
</template>
<script>
import overlay from "./components/overlay";
import about from "./components/about";
export default {
name: "App",
components: {
about,
overlay
}
};
</script>
You can do something like this, in your app.vue set a variable to show your overlay.vue or not. And then in the overlay.vue set a props that change the style of your component. This solution is not using a dom manipulation.
app.vue
<template>
<div id="app">
<overlay :show="show_overlay"></overlay>
<about></about>
</div>
</template>
<script>
import overlay from "./components/overlay";
import about from "./components/about";
export default {
name: "App",
data(){
return {
show_overlay:false
}
},
components: {
about,
overlay
}
};
</script>
overlay.vue
<template>
<div class="overlay" :style="[(this.show) ? 'display:block' : 'display:none']"></div>
</template>
<script>
export default {
name: "overlay",
props:{
show:{
default:false,
type:Boolean
}
}
};
</script>
because the two components are siblings and not imported in each other I coulden't use $ref and the best choice is to use Store
this is my store code
import Vue from "vue";
import Vuex from "vuex";
Vue.use(Vuex);
export default new Vuex.Store({
state: {
showOverlay: false
},
mutations: {
//showing the overlay
TOGGLE_OVERLAY(state, payload) {
state.showOverlay = payload;
}
},
actions: {
//showing the overlay
toggleOverlay(context, payload) {
context.commit("TOGGLE_OVERLAY", payload);
}
},
getters: {
getStatus: state => state.showOverlay
}
});
and here where i dispatch it. I dispatch it from about.vue or any other component as well
<a #click.prevent="toggleOverlay" href="#"><i class="fas fa-play"></i></a>
methods: {
toggleOverlay() {
this.$store.state.showOverlay = !this.$store.state.showOverlay;
this.$store.dispatch(
"toggleOverlay",
this.$store.state.showOverlay
);
}
}

Is there a way to leak parent css to child components in Vue?

I've got App.vue:
<template>
<div>
<p class="text">Hello World</p>
</div>
</template>
<script>
import ParentComponent from '../components/ParentComponent'
export default {
components: {
ParentComponent
}
}
</script>
And then I have ParentComponent:
<template>
<div>
<p class="text">Hello World</p>
<ChildComponent />
</div>
</template>
<script>
import ChildComponent from '../ChildComponent'
export default {
components: {
ChildComponent
}
}
</script>
<style>
.text {
font-size: 30px
}
</style>
ChildComponent:
<template>
<p class="text">Hello World</p>
</template>
<script>
export default {
}
</script>
<style>
</style>
Now, whatever styles I have in ParentComponent, I want the child component to have that style as well.
However, I don't want App.vue to have that style. Also if ChildComponent has any other components, then they should inherit the style of ParentComponent as well. Like ParentComponent is the style provider.
I really don't have any code to show. I just want to know if this is possible and how?
You can simply create an css class in the parent component with the style you want to have the children use. Then you simply use the class in a child.
The example you have is actually working as how you want it to be, as long as the child-component indeed nested as a child in the parent component.
What we do in our firm is that we always wrap components with a class with the same name as the component name. This makes it really obvious what you are styling if you are doing some weird parent type styling.
ParentComponent:
<template>
<div>
<p class="text">Hello World</p>
<ChildComponent />
</div>
</template>
<script>
import ChildComponent from '../ChildComponent'
export default {
components: {
ChildComponent
}
}
</script>
<style>
.some-class-name {
/*...*/
}
.text {
font-size: 30px
}
</style>
ChildComponent:
<template>
<div class="some-class-name">
<p class="text">Hello World</p>
</div>
</template>
<script>
export default {
}
</script>
<style>
</style>

Vue.js cannot use to <slot> to render the parent component

I just try to follow the example about the use of slot on the Vue official site. But it failed, I have made the code very short
parent component
<template>
<subMenuTemp>
<div class="text" >
parent content
</div>
</subMenuTemp>
</template>
<script>
import subMenuTemp from 'src/test/testChildren.vue'
export default {
data() {
},
components: {
subMenuTemp
}
}
</script>
children component another .vue file
<template>
<div class="content">
<slot>
old content
</slot>
</div>
</template>
<script>
export default {
}
</script>
although the code is very short, I still cannot find where is my fault
Make sure to include the two components in your main.js or some .js file that imports Vue. It should look like this:
import Vue from 'vue'
import App from './App'
import subMenuTemp from './test/testChildren.vue'
new Vue({
el: '#app',
template: '<App/>',
components: { App, subMenuTemp }
})
You don't need to register all components in the main file as pointed in other answers.
You just need to import the child component into the parent component just as you do.
See a here: https://codesandbox.io/s/vue-template-oy15j?fontsize=14
// App.vue
<template>
<div id="app">
<parent-component message="Hello Vue !"/>
</div>
</template>
<script>
import ParentComponent from "./components/ParentComponent";
export default {
name: "App",
components: { ParentComponent }
};
</script>
// ParentComponent.vue
<template>
<child-component>
<div class="test-parent">{{ message }}</div>
</child-component>
</template>
<script>
import ChildComponent from "./ChildComponent";
export default {
name: "ParentComponent",
components: { ChildComponent },
props: {
message: String
}
};
</script>
// ChildComponent.vue
<template>
<div class="test-child">
<slot>default content</slot>
</div>
</template>
<script>
export default {
name: "ChildComponent"
};
</script>
<!-- Result -->
<div id="app">
<div class="test-child">
<div class="test-parent">Hello Vue !</div>
</div>
</div>

Categories

Resources