vuejs update parent data from child component

I'm starting to play with vuejs (2.0). I built a simple page with one component in it. The page has one Vue instance with data. On that page I registered and added the component to html. The component has one input[type=text]. I want that value to reflect on the parent (main Vue instance).

How do I correctly update the component's parent data? Passing a bound prop from the parent is not good and throws some warnings to the console. They have something in their doc but it is not working.

Answers:

Answer

Two-way binding has been deprecated in Vue 2.0 in favor of using a more event-driven architecture. In general, a child should not mutate its props. Rather, it should $emit events and let the parent respond to those events.

In your specific case, you could use a custom component with v-model. This is a special syntax which allows for something close to two-way binding, but is actually a shorthand for the event-driven architecture described above. You can read about it here -> https://vuejs.org/v2/guide/components.html#Form-Input-Components-using-Custom-Events.

Here's a simple example:

Vue.component('child', {
  template: '#child',
  
  //The child has a prop named 'value'. v-model will automatically bind to this prop
  props: ['value'],
  methods: {
    updateValue: function (value) {
      this.$emit('input', value);
    }
  }
});

new Vue({
  el: '#app',
  data: {
    parentValue: 'hello'
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.13/vue.js"></script>

<div id="app">
  <p>Parent value: {{parentValue}}</p>
  <child v-model="parentValue"></child>
</div>

<template id="child">
   <input type="text" v-bind:value="value" v-on:input="updateValue($event.target.value)">
</template>


The docs state that

<custom-input v-bind:value="something" v-on:input="something = arguments[0]"></custom-input>

is equivalent to

<custom-input v-model="something"></custom-input>

That is why the prop on the child needs to be named value, and why the child needs to $emit an event named input.

Answer

From the documentation:

In Vue.js, the parent-child component relationship can be summarized as props down, events up. The parent passes data down to the child via props, and the child sends messages to the parent via events. Let’s see how they work next.

enter image description here

How to pass props

Following is the code to pass props to a child element:

<div>
  <input v-model="parentMsg">
  <br>
  <child v-bind:my-message="parentMsg"></child>
</div>

How to emit event

HTML:

<div id="counter-event-example">
  <p>{{ total }}</p>
  <button-counter v-on:increment="incrementTotal"></button-counter>
  <button-counter v-on:increment="incrementTotal"></button-counter>
</div>

JS:

Vue.component('button-counter', {
  template: '<button v-on:click="increment">{{ counter }}</button>',
  data: function () {
    return {
      counter: 0
    }
  },
  methods: {
    increment: function () {
      this.counter += 1
      this.$emit('increment')
    }
  },
})
new Vue({
  el: '#counter-event-example',
  data: {
    total: 0
  },
  methods: {
    incrementTotal: function () {
      this.total += 1
    }
  }
})
Answer

In child component:

this.$emit('eventname', this.variable)

In parent component:

<component @eventname="updateparent"></component>

methods: {
    updateparent(variable) {
        this.parentvariable = variable
    }
}
Answer

Child Component

Use this.$emit('event_name') to send an event to the parent component.

enter image description here

Parent Component

In order to listen to that event in the parent component, we do v-on:event_name and a method (ex. handleChange) that we want to execute on that event occurs

enter image description here

Done :)

Answer

I agree with the event emitting and v-model answers for those above. However, I thought I would post what I found about components with multiple form elements that want to emit back to their parent since this seems one of the first articles returned by google.

I know the question specifies a single input, but this seemed the closest match and might save people some time with similar vue components. Also, no one has mentioned the .sync modifier yet.

As far as I know, the v-model solution is only suited to one input returning to their parent. I took a bit of time looking for it but Vue (2.3.0) documentation does show how to sync multiple props sent into the component back to the parent (via emit of course).

It is appropriately called the .sync modifier.

Here is what the documentation says:

In some cases, we may need “two-way binding” for a prop. Unfortunately, true two-way binding can create maintenance issues, because child components can mutate the parent without the source of that mutation being obvious in both the parent and the child.

That’s why instead, we recommend emitting events in the pattern of update:myPropName. For example, in a hypothetical component with a title prop, we could communicate the intent of assigning a new value with:

this.$emit('update:title', newTitle)

Then the parent can listen to that event and update a local data property, if it wants to. For example:

<text-document   
 v-bind:title="doc.title"  
 v-on:update:title="doc.title = $event"
></text-document>

For convenience, we offer a shorthand for this pattern with the .sync modifier:

<text-document v-bind:title.sync="doc.title"></text-document>

You can also sync multiple at a time by sending through an object. Check out the documentation here

Answer

It is also possible to pass props as Object or Array. In this case data will be two-way binded:

(This is noted at the end of topic: https://vuejs.org/v2/guide/components.html#One-Way-Data-Flow )

Vue.component('child', {
  template: '#child',
  props: {post: Object},
  methods: {
    updateValue: function () {
      this.$emit('changed');
    }
  }
});

new Vue({
  el: '#app',
  data: {
    post: {msg: 'hello'},
    changed: false
  },
  methods: {
    saveChanges() {
        this.changed = true;
    }
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.13/vue.js"></script>

<div id="app">
  <p>Parent value: {{post.msg}}</p>
  <p v-if="changed == true">Parent msg: Data been changed - received signal from child!</p>
  <child :post="post" v-on:changed="saveChanges"></child>
</div>

<template id="child">
   <input type="text" v-model="post.msg" v-on:input="updateValue()">
</template>

Answer

The way more simple is use this.$emit

Father.vue

<template>
  <div>
    <h1>{{ message }}</h1>
    <child v-on:listenerChild="listenerChild"/>
  </div>
</template>

<script>
import Child from "./Child";
export default {
  name: "Father",
  data() {
    return {
      message: "Where are you, my Child?"
    };
  },
  components: {
    Child
  },
  methods: {
    listenerChild(reply) {
      this.message = reply;
    }
  }
};
</script>

Child.vue

<template>
  <div>
    <button @click="replyDaddy">Reply Daddy</button>
  </div>
</template>

<script>
export default {
  name: "Child",
  methods: {
    replyDaddy() {
      this.$emit("listenerChild", "I'm here my Daddy!");
    }
  }
};
</script>

My full example: https://codesandbox.io/s/update-parent-property-ufj4b

Answer

The correct way is to $emit() an event in the child component that the main Vue instance listens for.

// Child.js
Vue.component('child', {
  methods: {
    notifyParent: function() {
      this.$emit('my-event', 42);
    }
  }
});

// Parent.js
Vue.component('parent', {
  template: '<child v-on:my-event="onEvent($event)"></child>',
  methods: {
    onEvent: function(ev) {
      v; // 42
    }
  }
});
Answer

1) Child Compnent : you can use like this in child component write like this : this.formValue is to send some data to parent component

this.$emit('send',this.formValue)

2) Parrent Compnenet : and in parrent component tag recieve send variable like this : and this is the code to recevie that child compnent data in parent component tag

@send="newformValue"
Answer

Another way is to pass a reference of your setter from the parent as a prop to the child component, similar to how they do it in React. Say, you have a method updateValue on the parent to update the value, you could instantiate the child component like so: <child :updateValue="updateValue"></child>. Then on the child you will have a corresponding prop: props: {updateValue: Function}, and in the template call the method when the input changes: <input @input="updateValue($event.target.value)">.

Answer

I don't know why, but I just successfully updated parent data with using data as object, :set & computed

Parent.vue

<!-- check inventory status - component -->
    <CheckInventory :inventory="inventory"></CheckInventory>

data() {
            return {
                inventory: {
                    status: null
                },
            }
        },

Child.vue

<div :set="checkInventory">

props: ['inventory'],

computed: {
            checkInventory() {

                this.inventory.status = "Out of stock";
                return this.inventory.status;

            },
        }
Answer

his example will tell you how to pass input value to parent on submit button.

First define eventBus as new Vue.

//main.js
import Vue from 'vue';
export const eventBus = new Vue();

Pass your input value via Emit.
//Sender Page
import { eventBus } from "../main";
methods: {
//passing data via eventbus
    resetSegmentbtn: function(InputValue) {
        eventBus.$emit("resetAllSegment", InputValue);
    }
}

//Receiver Page
import { eventBus } from "../main";

created() {
     eventBus.$on("resetAllSegment", data => {
         console.log(data);//fetching data
    });
}
Answer

I think this will do the trick:

@change="$emit(variable)"

Tags

Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us

©2020 All rights reserved.