zeomega
zeomega

Reputation: 355

change parent props from child component in vuejs2

I want to change the parent's prop's value from a child component. This works great in vuejs 1 but not in vue 2 (I want to use it in vue.js 2).

Here is a small example :

HTML

<div id="app">
   <parent :content="{value:'hello parent'}"><</parent>
</div>

JavaScript

var parent = {
  template: '<child :content="content"></child>',
  props: ['content'],
};

var child = {
  template: '<div>{{ content.value }}<button @click="change">change me</button></div>',
  props: ['content'],
  methods: {
    change() {
      this.content.value = "Value changed !";
    }
  }
};

Vue.component('child', child);
Vue.component('parent', parent);

new Vue({
  el: '#app',
});

https://jsfiddle.net/f5gt94f2/

Upvotes: 1

Views: 5330

Answers (2)

acdcjunior
acdcjunior

Reputation: 135752

tl;dr: in vue2, you need to use the .sync modifier.


Create a local copy of the content prop in the parent's data (see reason here).

var parent = {
  ...
  data() {
    return {
      localContent: this.content // creating a local copy, so we can mutate and react to it
    }
  }
};

Now, pass that localContent to the child, not content. And pass it using .sync so it can be updated:

var parent = {
  template: '<div><child :content.sync="localContent"></child></div>',
  ...                     //     ^^^^^^^^^^^^^^^^^^^^-- changed here

Now, in the child, don't assign to this.content.value, emit an update event instead:

var child = {
    ...
    change() {
      this.$emit('update:content', {value: "Value changed !"})
    }
  }
};

This event, with the new value, will be picked up by the parent and will update its localContent which also will, in consequence, update the child's content prop.

Final running code below.

var parent = {
  template: '<div><child :content.sync="localContent"></child><br>At parent: {{ localContent }}</div>',
  props: ['content'],
  data() {
    return {
      localContent: this.content
    }
  }
};

var child = {
  template: '<div>At child: {{ content.value }}<button @click="change">change me</button></div>',
  props: ['content'],
  methods: {
    change() {
      this.$emit('update:content', {value: "Value changed !"})
    }
  }
};

Vue.component('child', child);
Vue.component('parent', parent);

new Vue({
  el: '#app'
});
<script src="https://unpkg.com/[email protected]/dist/vue.js"></script>

<div id="app">
  <parent :content="{value:'hello parent'}"></parent>
</div>

Upvotes: 3

Ru Chern Chong
Ru Chern Chong

Reputation: 3756

You will have to use emit events for this

Parent:

<child :content="content" @updateParent="updateValue"></child>

methods: {
  updateValue (value) {
    // Your code here
  }
}

Child:

props: ['content'],
methods: {
  change () {
    this.$emit('updateParent', value)
  }
}

https://v2.vuejs.org/v2/guide/components.html#Custom-Events

Upvotes: 1

Related Questions