In Parent I included one ChildComponent as such:
<template>
<div>
<ChildComponent :value="var1" v-slot="{value}">
<input v-model="value.name"/>
</ChildComponent>
</div>
</template>
<script>
import ChildComponent from "../components/ChildComponent.vue";
export default {
components: { ChildComponent },
data() {
return {
var1: {
name: "Vue.js",
message: "LocalHost"
}
};
}
</script>
ChildComponent:
<template>
<div>
<div id="divToShow" v-if="this.$slots.default || this.$scopedSlots.value">
<slot/>
</div>
<div v-else id="divFallback">
<p>Nothing in your input component!</p>
</div>
</div>
</template>
<script>
export default {
name: "ChildComponent",
props: {
value: String
}
}
</script>
However, divToShow does not appear, so divFallback takes its place. How should I go about making divToShow show up when Parent defines a (seemingly) dynamic name slot like this?
Related
I am trying to practice vue application using props but when I click on the the name, I tried to do console.log the problem but it hasn't helped me. Maybe I am new to filter option but I want to know what I am doing wrong?
App.vue
<template>
<div id="app">
<h1>All Friends</h1>
<AllFriends :Totalfriends="friends" />
<h1>Online Friends</h1>
<OnlineFriends :Totalfriends="friends" #toggleStatus="toggleStatus" />
</div>
</template>
<script>
import AllFriends from "./components/AllFriends"
import OnlineFriends from "./components/OnlineFriends"
export default {
name: 'App',
components: {
AllFriends,
OnlineFriends
},
data(){
return{
friends: [
{name:'Mario', online: true},
{name:'Luigi', online: false},
{name:'Todd', online: true},
{name:'Bowzer', online: false}
]
}
},
methods: {
toggleStatus(payload){
this.friends = this.friends.filter((friend)=>{
if(friend !== payload){
console.log(friend)
}
})
}
}
}
</script>
OnlineFriends.vue
<template>
<div>
Online Friends
<div v-for="(friends, index) in Totalfriends" :key="index">
<p #click="toggleStatus(friends.name)" v-if="friends.online">{{friends.name}}</p>
</div>
</div>
</template>
<script>
export default {
props:["Totalfriends"],
methods: {
toggleStatus(friend){
this.$emit("toggleStatus",{friend})
}
}
}
</script>
AllFriends.vue
<template>
<div>
All Friends
<div v-for="(friend, index) of Totalfriends" :key="index">
<p>{{friend.name}}</p>
</div>
</div>
</template>
<script>
export default {
name: "AllFriends",
props: ["Totalfriends"]
}
</script>
I am trying to change prop of my component if it is rendered more than once. By default the first prop will have fixed value but the second calling of the component will get it's prop from parent's parent. In my example, the value from App.vue doesn't change prop going in myBox.vue
Here is my link
App.vue
<template>
<div id="app">
{{years}}
<myBox :years="years"/>
<button #click="changeProp">Change prop</button>
</div>
</template>
<script>
import myBox from "./components/myBox";
export default {
name: "App",
components: {
myBox
},
data() {
return {
years: ""
};
},
methods: {
changeProp() {
this.years = 100;
}
}
};
</script>
mySelect.vue
<template>
<div class="select">
<select>
{{years}}
<option v-for=" (i, index) in years" :key="index">{{i}}</option>
</select>
</div>
</template>
<script>
import myBox from "./myBox";
export default {
data() {
return {};
},
components: {
myBox
},
props: ["years"]
};
</script>
<style>
.select {
width: 100px;
height: 100px;
}
</style>
mySelect.vue
<template>
<div class="box">
<mySelect :years="24"/>
<mySelect :years="24"/>
<mySelect :years="24"/>
</div>
</template>
<script>
import mySelect from "./mySelect.vue";
export default {
data() {
return {
//years: [2000, 2001, 2002, 2003, 2004, 2005, 2006],
value: 5
};
},
components: {
mySelect
}
};
</script>
<style>
div.box {
width: 100%;
height: auto;
background: lightblue;
}
</style>
Currently my code generates the second and thrid component dynamic with v-if and takes the default props value, whereas I want it to get from parent's parent.
Is it possible?
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
);
}
}
I just want to use an independant component many times like this :
<main-component>
<other-component />
<other-component />
</main-component>
I have a problem with variable in my other-component.
In the code bellow I use show var to display or not content according button click. I want to display only the paragraph of the current component clicked
import otherComponent from '../../otherComponent'
// main component
export default {
name: 'main-component',
components: {
otherComponent
},
data () {
return {
}
},
}
<template>
<div>
<other-component />
<other-component />
</div>
</template>
// other component
export default {
name: 'other-component',
data () {
return {
show: false
}
},
methods: {
toggle(){
this.show = !this.show
}
}
<template>
<div>
<button #click="toggle">Toggle</button>
<p v-show="show">1</p>
</div>
</template
When I click in button the two p are displayed. Why ?
If you nest components inside one another, you need to use slots: https://v2.vuejs.org/v2/guide/components-slots.html#ad.
For the following code to render correctly:
<main-component>
<other-component />
<other-component />
</main-component>
Your main-component component needs to have <slot /> in it's template:
<template>
<div>
<slot />
</div>
</template>
Then <slot /> will be replaced by ...
<other-component />
<other-component />
...when it renders. Which means main-component does not need to import or have any reference to otherComponent.
I have an example on CodeSandbox of this working: https://codesandbox.io/embed/vue-template-gblx0.
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>