I have included an $emit in an axios post of a child component as follows.
axios.post('/api/register', qdata)
.then((response) => {
this.$emit('userUpdated', response.data)
})
In the parent component, I have a div element in the html code containing a v-on, which refers to the userUpdated of the $emit.
<div id="username" v-on:userUpdated="nameUpddated($event)">
<p>{{userid}}</p>
</div>
Finally, the script section of the parent contains the following function called by the v-on.
nameUpddated: function (updatedUser) {
this.userid = updatedUser
}
I have validated that the axios returns a proper value in the Child component. However, the function in the parent never gets called.
In your parent component use child component name instead of div.
Edit: I also added v-if to conditionally show the component.
<child-component v-if="isVisible" id="username" v-on:userUpdated="nameUpddated($event)">
<p>{{userid}}</p>
</child-component>
Also, you need to add a data property to show the component conditionally (initially hidden).
data () {
return {
isVisible: false
}
}
Now, it is up to you at what point you want to show the child component. You would simply change isVisible to true.
After making this change, it should work as expected.
Note: please remember to register the child component properly as well in your parent component:
import childComponent from '#/components/childComponent'
export default {
components: {
childComponent
}
}
Related
I'm trying to use a props from the parent component to use it as a data in my child component.
parent component :
<ChangeCommentModal :comment="this.modalInfo.comment" />
And child component (ChangeCommentModal) :
props: ['comment'],
data() {
return {
localComment: this.comment,
};
}
The localComment variable get the value but I can't use it in a v-model in this child component :
<textarea id="message" rows="2" v-model="localComment"></textarea>
The textarea is empty when the component is displayed.
Any idea ? Thanks !
Seems your code is only assign this.comment to localComment once when the child component is init. Instead, you can use watcher to watch the change of prop comment and assign it to the localComment everytime you update from the parent component. Let's try to see if resolve your problem
watch() {
comment(value) {
this.localComment = value
}
}
I have 3 vue.js nested components: main, parent, child.
The parent component load basic data, the child is a simple countdown widget which needs just a data to be configured.
If I set the parent script with static data (IE deadline='2019-12-12') the child show the widget working nice, but if I use dynamic data it generate error.
I'm using computed to pass data to the child component and if I debug it using an alert I see 2 alerts: undefined and then the correct date.
The issue is the first computed data (undefined) crash the widget, so how to create child component using updated (loaded) data?
Parent template:
<template>
<div>
<flip-countdown :deadline=deadline></flip-countdown>
</div>
</template>
Parent Script: it needs to be fixed
export default {
components: {FlipCountdown},
props: ['event'],
computed: {
deadline: function () {
if (typeof(this.event.date)!="undefined") {
//alert(this.event.date)
return this.event.date;
} else {
return "2019-05-21 00:00:00";
}
},
},
Child template: it works
<template>
<div>
<flip-countdown :deadline="deadline"></flip-countdown>
</div>
</template>
Your parent component passes the deadline to its child component before the mounted lifecycle hook fires. Your child component sets its deadline with the initial value of undefined.
You should make deadline a computed property in child component:
computed: {
internalDeadline() {
return this.deadline; // comming from props
}
}
Then you can use internalDeadline in child.
Alternatively, you could wait to render the child component until deadline is defined:
<flip-countdown v-if="deadline !== undefined" :deadline="deadline"></flip-countdown>
I want to pass down the changes made in parent component data values to its child components each time the value changes in parent how can i achieve it in vue.js. I am using 3 custom components that have to reflect the current value of the parent component each time. p.s i am new to vue.js
you just need to pass it as a prop. In your template:
<my-component :my-prop="myData" />
and in your script tag:
export default {
data() {
myData: 0,
}
}
Whenever you update this.data, the component will update its view, as the prop will have changed
Data is typically passed one-way from parent to child components via props. See the documentation on this here.
Example:
// register the child component
Vue.component('child', {
props: ['myProp'],
template: '<span>{{ myProp }}</span>'
})
// in parent component
<child :my-prop="hello"></child>
Thanks for reading my question.
I have doubts about how to accomplish this in my Vue.js app.
Parent Component: App.vue
Child Components: Loading.vue, ProductsList.vue, NoProductList.vue
The App component is the container. When the page loads, the Loading component is displayed.
The Loading component then checks for products. If there are products the Loading component will return the products as an object.
If there aren't any products the Loading component will return null.
How do I tell the App component which component to use based on the Loading components return value? ie.. Load the ProductsList component if there are products and the NoProduct component when there aren't any products?.
What's the correct way to do notify the parent component about which component it should use in Vue?
Should I use $emit (pass data from child to parent), State Management https://v2.vuejs.org/v2/guide/state-management.html#Simple-State-Management-from-Scratch or a Bus component?
Some code...
Loading.vue component (child):
export default {
name: 'loading',
data () {
return {
message: ''
}
},
mounted: function () {
this.loadingProcess();
},
methods: {
loadingProcess: function () {
//process
this.$emit('found-products', 'hola');
}
}
App.vue component (parent):
<template>
<div>
<div id="resultComponent" #found-products="checkProductsList">
<loading></loading>
...
</div>
</div>
</template>
Thanks in advance.
For parent-child interactions, the correct way is for the child to $emit and the parent to set props.
State management and buses are for more complex systems where data must be shared by not-closely-related components.
I have a very small app that has a donation form. The form walks the user through the steps of filling in information. I have a main component, which is the form wrapper and the main Vue instance which holds all of the form data (model). All of the child components are steps within the donation process. Each child component has input fields that are to be filled out and those field will update the parent model so that I have all of the form data in the parent model when I submit the form. Here is how the components are put together:
<donation-form></donation-form> // Main/Parent component
Inside the donation-form component:
<template>
<form action="/" id="give">
<div id="inner-form-wrapper" :class="sliderClass">
<step1></step1>
<step2></step2>
<step3></step3>
</div>
<nav-buttons></nav-buttons>
</form>
</template>
Right now, I am setting the data from the inputs in each child component and then I have a watch method that is watching for fields to update and then I am pushing them to the $root by doing this...
watch: {
amount() {
this.$root.donation.amount = this.amount;
}
}
The problem is that one of my steps I have a lot of fields and I seem to be writing some repetitive code. Also, I'm sure this is not the best way to do this.
I tried passing the data as a prop to my child components but it seems that I cannot change the props in my child component.
What would be a better way to update the root instance, or even a parent instance besides add a watch to every value in my child components?
More examples
Here is my step2.vue file - step2 vue file
Here is my donation-form.vue file - donation-form vue file
You can use custom events to send the data back.
To work with custom events, your data should be in the parent component, and pass down to children as props:
<step1 :someValue="value" />
and now you want to receive updated data from child, so add an event to it:
<step1 :someValue="value" #update="onStep1Update" />
your child components will emit the event and pass data as arguments:
this.$emit('update', newData)
the parent component:
methods: {
onStep1Update (newData) {
this.value = newData
}
}
Here is a simple example with custom events:
http://codepen.io/CodinCat/pen/QdKKBa?editors=1010
And if all the step1, step2 and step3 contain tons of fields and data, you can just encapsulate these data in child components (if the parent component doesn't care about these row data).
So each child has its own data and bind with <input />
<input v-model="data1" />
<input v-model="data2" />
But the same, you will send the result data back via events.
const result = this.data1 * 10 + this.data2 * 5
this.$emit('update', result)
(again, if your application becomes more and more complex, vuex will be the solution.
Personally I prefer having a generic function for updating the parent, when working with forms, instead of writing a method for every child. To illustrate – a bit condensed – like this in the parent:
<template lang="pug">
child-component(:field="form.name" fieldname="name" #update="sync")
</template>
<script>
export default {
methods: {
sync: function(args) {
this.form[args.field] = args.value
}
}
}
</script>
And in the child component:
<template lang="pug">
input(#input="refresh($event.target.value)")
</template>
<script>
export default {
props: ['field', 'fieldname'],
methods: {
refresh: function(value) {
this.$emit('update', {'value': value, 'field': this.fieldname});
}
}
}
</script>
For your case you can use v-model like following:
<form action="/" id="give">
<div id="inner-form-wrapper" :class="sliderClass">
<step1 v-model="step1Var"></step1>
<step2 v-model="step2Var"></step2>
<step3 v-model="step3Var"></step3>
</div>
<nav-buttons></nav-buttons>
</form>
v-model is essentially syntax sugar for updating data on user input events.
<input v-model="something">
is just syntactic sugar for:
<input v-bind:value="something" v-on:input="something = $event.target.value">
You can pass a prop : value in the child components, and on change of input field call following which will change the step1Var variable.
this.$emit('input', opt)
You can have a look at this answer where you can see implementation of such component where a variable is passed thouugh v-model.