Hello I have a component Carousel, and I have method:
carousel () {
return this.$refs.carousel
}
When I try pass to prop of other component, I get undefined in prop data, why?
<Dots :carousel="carousel()" />
In child component I have:
export default {
name: 'Dots',
props: ['carousel']
}
In mounted when I try call console.log(this.carousel), I get undifined. But I need get a component data of Carousel. How I can do it?
Sandbox: https://codesandbox.io/s/flamboyant-monad-5bhjz?file=/src/components/Test.vue
You can set a function in carousel to return the data you want to send to dots. Then, in the parent component, set its return value to an attribute in data which will be passed as a prop:
const dotsComponent = Vue.component('dotsComponent', {
template: '#dotsComponent',
props: ['carousel']
});
const carouselComponent = Vue.component('carouselComponent', {
template: '#carouselComponent',
data() { return { id:1 } },
methods: {
getData() { return { id: this.id } }
}
});
new Vue({
el: "#app",
components: { dotsComponent, carouselComponent },
data() { return { carousel:null } },
mounted() { this.carousel = this.$refs.carousel.getData(); }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<div><carousel-component ref="carousel"/></div>
<div><dots-component :carousel="carousel"/></div>
</div>
<template id="dotsComponent"><p>Dots: {{carousel}}</p></template>
<template id="carouselComponent"><p>Carousel</p></template>
You could pass the ref directly without using a method any other property :
<Dots :carousel="$refs.carousel" />
So I have this set-up, which crashes on v-for construct of table-component. It shows an error: "Property or method "tablesList" is not defined on the instance but referenced during render". If I omit v-for table-component renders. If I access this data from "container" component all is fine. So the problem is in accessing data from child template in parent template.
What am I doing wrong?
let container = Vue.component("container", {
props: ["item"],
template: `<div class="container">
<table-component v-for="item in tablesList"></table-component>
</div>`
});
let table = Vue.component("table-component", {
props: ["item"],
template: `<div class="table">
this is a table
</div>`
});
let app = new Vue({
el: "#app",
data() {
return {
containersList: [],
tablesList: [{item:'item'}]
};
},
methods: {
anyMethod() {
}
}
});
</script>
You are using tablesList in container component But you defined it in app.
You need to add tablesList in container like below,
let container = Vue.component("container", {
props: ["item"],
data: () => {
return {
tablesList: [{item:'item'}]
}
},
template: `<div class="container">
<table-component v-for="item in tablesList"></table-component>
</div>`
});
NOTE: Use v-bind:key when use v-for.
You need to define tablesList in props => https://v2.vuejs.org/v2/guide/components.html#Passing-Data-to-Child-Components-with-Props
I am trying to pass the name from data to my settingTemplate.
However, I have not been able to make it work. Could anyone advice how I should approach this? I am new to Vue.
app.js
var app = new Vue({
el: '#app',
components: {
settingTemplate
},
data: {
name: 'Elon'
}
})
setting-template.js
const settingTemplate = {
template:
`<div class="d-flex flex-column text-md-center">
<div class="p-2">
<b-btn id="popoverButton-disable" variant="primary"></b-btn>
</div>
<div class="p-2">
<b-popover :disabled.sync="disabled" target="popoverButton-disable" title="{{name}}">
<a>Profile</a> | <a>Logout</a>
</b-popover>
</div>
</div>`
,
data() {
return {
disabled: false
}
},
methods: {
disableByRef() {
if (this.disabled){
this.$refs.popover.$emit('enable')
}else{
this.$refs.popover.$emit('disable')
}
}
},
props: ['name']
}
You should pass name to your component by attribute, not by data:
<div id="app">
<setting-template name="Elon" />
</div>
Here you can check working example:
https://codepen.io/anon/pen/dwrOqY?editors=1111
data is component private data - it's not passed to child components.
If you still need name in your main component data you can pass it to the child component like this:
<div id="app">
<setting-template :name="name" />
</div>
var app = new Vue({
el: '#app',
components: {
settingTemplate
},
data: {
name: 'Leon'
}
})
https://codepen.io/anon/pen/qLvqeO?editors=1111
I have a component with following template:
<div v-for:"item in store" v-bind:key="item.type">
<a>{{item.type}}</a>
</div>
I have another component called 'StoreComponent'
On click of a element in first component I want to clear the current component and show the StoreComponent and able to pass item.type to StoreComponent.
I don't want to use router-link or router.push as I don't want to create a new url but override the current component with the new one depending on the item.type value.
StoreComponent.vue
export default{
name: 'StoreComponent',
props: ['item'],
data: function () {
return {
datum: this.item
}
},
methods: {
//custom methods
}
}
You could use dynamic components and pass the item-type as a prop.
Vue.component('foo', {
name: 'foo',
template: '#foo'
});
Vue.component('bar', {
name: 'bar',
template: '#bar',
props: ['test']
});
new Vue({
el: "#app",
data: {
theComponent: 'foo', // this is the 'name' of the current component
somethingWeWantToPass: {
test: 123 // the prop we are passing
},
},
methods: {
goFoo: function() {
this.theComponent = 'foo';
},
goBar: function() {
this.theComponent = 'bar';
},
}
})
<script src="https://unpkg.com/vue"></script>
<div id="app">
<button #click="goFoo">Foo</button>
<button #click="goBar">Bar</button>
<component :is="theComponent" v-bind="somethingWeWantToPass"></component>
</div>
<template id="foo">
<div>
Foo
</div>
</template>
<template id="bar">
<div>
Bar
<div>This is a prop: {{ this.test }}</div>
</div>
</template>
I am new in Vue Js. So, I am facing a problem to changes data value from another component.
I have a component A:
<template>
<div id="app">
<p v-on:click="test ()">Something</p>
</div>
</template>
import B from '../components/B.vue';
export default {
components: {
B
},
methods: {
test: function() {
B.data().myData = 124
B.data().isActive = true
console.log(B.data().myData);
console.log(B.data().isActive);
}
}
}
Component B:
export default {
data() {
return {
myData: 123,
isActive: false
}
}
}
It still component B data.
But it cannot be affected component B data. I want to data changes of component B from component A. How can I do that?
Please explain me in details. I have seen vue js props attribute but I don't understand.
You're looking for Vuex.
It's the centralized store for all the data in your applications.
Take a look at their documentation, it should be pretty straightforward.
You can pass down props to the component B. These props can be updated by the parent component. You can think of B as a stupid component that just renders what the parent tells it to rendern. Example:
// Component A
<template>
<div id="app">
<p v-on:click="test ()">Something</p>
<b data="myData" isActive="myIsActive"></b>
</div>
</template>
<script>
import B from '../components/B.vue';
export default {
components: {
B
},
data() {
return {
myData: 0,
myIsActive: false,
};
},
methods: {
test: function() {
this.myData = 123
this.myIsActive = true
}
}
}
</script>
// Component B
<template>
<div>{{ data }}{{ isActive }}</div>
</template>
<script>
export default {
props: {
data: Number,
isActive: Boolean
};
</script>
There are few ways...
if your components have a parent child relationship you can pass data values from parent into child.
If your want to communicate back to parent component when child component has changed something, you can use vuejs event emitter(custom event) to emit a event when data value change and that event can be listened in another component and do what you want.
If your components doesn't have a relationship, then you have to use use something else than above things. You can use two things.one is event bus, other one is state management library.for vue there is a official state management library called VueX.it is very easy to use.if you want to use something else than vuex, you can use it such as redux, mobx etc.
This documentation has everything what you want to know. I don't want to put any code, because of doc is very clear.
VueX is the most preferable way to do this! Very easy to use..
https://v2.vuejs.org/v2/guide/components.html
//component A
Vue.component('my-button', {
props: ['title'],
template: `<button v-on:click="$emit('add-value')">{{title}}</button>`
});
Vue.component('my-viewer', {
props: ['counter'],
template: `<button>{{counter}}</button>`
});
new Vue({
el: '#app',
data: {
counter: 0,
},
methods: {
doSomething: function() {
this.counter++;
}
}
})
Vue.component('blog-post', {
props: ['title'],
template: '<h3>{{ title }}</h3>'
});
//parent
new Vue({
el: '#blog-post-demo',
data: {
posts: [{
id: 1,
title: 'My journey with Vue'
},
{
id: 2,
title: 'Blogging with Vue'
},
{
id: 3,
title: 'Why Vue is so fun'
}
]
}
});
Vue.component('blog-post2', {
props: ['post'],
template: `
<div class="blog-post">
<h3>{{ post.title }}</h3>
<button v-on:click="$emit('enlarge-text')">
Enlarge text
</button>
<div v-html="post.content"></div>
</div>`
})
new Vue({
el: '#blog-posts-events-demo',
data: {
posts: [{
id: 1,
title: 'My journey with Vue'
},
{
id: 2,
title: 'Blogging with Vue'
},
{
id: 3,
title: 'Why Vue is so fun'
}
],
postFontSize: 1
},
methods: {
onEnlargeText: function() {
this.postFontSize++;
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<p>Two components adding & viewing value</p>
<div id="app">
<my-button :title="'Add Value'" v-on:add-value="doSomething"></my-button>
<my-viewer :counter="counter"></my-viewer>
</div>
<br>
<br>
<p>Passing Data to Child Components with Props (Parent to Child)</p>
<div id="blog-post-demo">
<blog-post v-for="post in posts" v-bind:key="post.id" v-bind:title="post.title"></blog-post>
</div>
<p>Listening to Child Components Events (Child to Parent)</p>
<div id="blog-posts-events-demo">
<div :style="{ fontSize: postFontSize + 'em' }">
<blog-post2 v-for="post in posts" v-bind:key="post.id" v-bind:post="post" v-on:enlarge-text="onEnlargeText"></blog-post2>
</div>
</div>
First, you need a parent so two component can communicate. when my-button component is clicked triggers an event add-value that calls doSomething() function, then updates the value & show it to my-viewer component.
HTML
<!--PARENT-->
<div id="app">
<!--CHILD COMPONENTS-->
<my-button :title="'Add Value'" v-on:add-value="doSomething"></my-button>
<my-viewer :counter="counter"></my-viewer>
</div>
VUE.JS
//component A
Vue.component('my-button',{
props:['title'],
template:`<button v-on:click="$emit('add-value')">{{title}}</button>`
});
//Component B
Vue.component('my-viewer',{
props:['counter'],
template:`<button>{{counter}}</button>`
});
//Parent
new Vue({
el: '#app',
data:{
counter:0,
},
methods:{
doSomething:function(){
this.counter++;
}
}
})
This is base on Vue Components Guide
Passing Data to Child Components with Props (Parent to Child)
VUE.JS
//component (child)
//Vue component must come first, else it won't work
Vue.component('blog-post', {
/*Props are custom attributes you can register on a component. When a
value is passed to a prop attribute, it becomes a property on that
component instance*/
props: ['title'],
template: '<h3>{{ title }}</h3>'
});
//parent
new Vue({
el: '#blog-post-demo',
data: {
posts: [
{ id: 1, title: 'My journey with Vue' },
{ id: 2, title: 'Blogging with Vue' },
{ id: 3, title: 'Why Vue is so fun' }
]
}
});
HTML:
v-for will loop on posts and pass data to blog-post component
<div id="blog-post-demo">
<blog-post v-for="post in posts"
v-bind:key="post.id"
v-bind:title="post.title"></blog-post>
</div>
Listening to Child Components Events (Child to Parent)
HTML
You must first register the event by v-on:enlarge-text="onEnlargeText" to use $emit and make sure that it's always set to lower case or it won't work properly. example enlargeText and Enlargetext will always be converted to enlargetext, thus use enlarge-text instead, because its easy to read & valid, for a brief explanation about $emit you can read it here
<div id="blog-posts-events-demo">
<div :style="{ fontSize: postFontSize + 'em' }">
<blog-post
v-for="post in posts"
v-bind:key="post.id"
v-bind:post="post"
v-on:enlarge-text="onEnlargeText"></blog-post>
</div>
</div>
VUE.JS
When user clicks the button the v-on:click="$emit('enlarge-text')" will trigger then calling the function onEnlargeText() in the parent
//component (child)
Vue.component('blog-post', {
props: ['post'],
template: `
<div class="blog-post">
<h3>{{ post.title }}</h3>
<button v-on:click="$emit('enlarge-text')">
Enlarge text
</button>
<div v-html="post.content"></div>
</div>`
})
//parent
new Vue({
el: '#blog-posts-events-demo',
data: {
posts: [
{ id: 1, title: 'My journey with Vue' },
{ id: 2, title: 'Blogging with Vue' },
{ id: 3, title: 'Why Vue is so fun' }
],
postFontSize: 1
},
methods:{
onEnlargeText:function(){
this.postFontSize++;
}
}
})
Actually props suck sometimes you got some old external library in jquyer and need just damn pass value. in 99% of time use props that do job but.
A) spend tons of hours debuging changing tones of code to pass variables
B) one line solution
Create main variable in data letmeknow as object {}
this.$root.letmeknow
then somewhere in code from component
this.$root.letmeknow = this;
and then boom i got component console.log( this.$root.letmeknow ) and see now can change some values