0
votes

I am testing the components of vue.js and I encountered the problem of updating a parent component when the child changes.

I have generated the project with vue-cli (webpack), and I am using components that have their own .vue file.

The code:

App.vue

<template>
   <div id="app">
     <h2>{{ title }}</h2>
      <div class="pie">
       <change-title :title="title"></change-title>
     </div>
   </div>
</template>

<script>      
  import ChangeTitle from './components/ChangeTitle'

  export default {
    components: {
      ChangeTitle
    },
    data () {
      return {
        title: 'The title'
      }
    }
  }
</script> 

ChangeTitle.vue

<template>
    <div>
        <input v-model="title">
    </div>
</template>

<script>
export default {
  props: ['title']
}
</script>

The problem When the application load displays the title attribute correctly, but when I type in the <change-title> component field the title attribute that is directly in the App.vue file is not updated.

Also it shows me the following message:

[Vue warn]: Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop's value. Prop being mutated: "title"

What is the way to connect the child component with its parent component?

Thanks..

1
It can not be taken as duplicate, since the link you indicate does not use component with its own file and does not use .vue extensionchalo
But answer will be same as this for you as well, also check this answerSaurabh

1 Answers

4
votes

Firstly, you need to make a copy of the prop and place in data and then bind to that using v-model because Vue doesn't want you to directly change the prop from inside the component, so, inside the created hook simply copy the prop to an attribute in data:

export default{
  props: ['title'],
  created() {
    this.val = this.title
  },
  data() {
    return {
      val: ''
    }
  }
}

Then bind to it using v-model:

<input v-model="val">

You next step is to send the data back to the parent when the value changes, which you can do inside a watcher, simply watch val inside your change-title component and $emit it:

  watch: {
    val() {
      this.$emit('title-updated', this.val);
    }
  }

Then you can listen for that event in in your parent like so:

<change-title :title="title" @title-updated="updateTitle">

And finally add the updateTitle method to change the title in your parent:

  methods: {
    updateTitle(title) {
      this.title = title;
    }
  }

Here's the JSFiddle for the entire thing: https://jsfiddle.net/90ws3sL6/