I'll-Be-Back
I'll-Be-Back

Reputation: 10838

Updating parent data via child component?

What is correct procedure to update parent data via child component?

In the child component - I am modifying parent data directly via props. I am not sure if this is wrong way to go about it.

According to the vue doc:

when the parent property updates, it will flow down to the child, but not the other way around.

Example child component :

<script>
    export default {

        props: ['user'],

        data: function () {
            return {
                linkName: '',
                linkValue: '',
            }
        },

        methods: {
            addLink: function (event) {
                event.preventDefault();
                this.$http.post('/user/link', {name: this.linkName, key: this.linkValue}).then(response => {
                    this.user.links.push(response.data);
                }, response => {
                      // Error
                    }
                });
            },
        }
    }
</script>

I have used this.user.links.push(response.data); which modify the data directly to the parent component via props: ['user']

Upvotes: 0

Views: 488

Answers (1)

Mani Jagadeesan
Mani Jagadeesan

Reputation: 24275

As you rightly said, the props is not meant to pass data from child to parent. The data binding is one-way only.

The correct procedure is for child component to send an event via $emit to the parent component, along with some value (optional).

In your case, you may do the following in the addLink method of child component:

this.$http.post('/user/link', {name: this.linkName, key: this.linkValue}).then(response => {
    this.$emit("update-user-links", response.data);  // Send an event to parent, with data
}, response => {
    // Error
});

And your parent can listen to it as follows:

<my-user-link-component :user="userData" v-on:update-user-links="addUserLink"></my-user-link-component>

or the short-hand syntax:

<my-user-link-component :user="userData" @update-user-links="addUserLink"></my-user-link-component>

In the above, you are assigning a method addUserLink to handle the child component's event. In your parent component, you need to define this method as follows:

methods: {
    // ... your other methods,
    addUserLink: function(linkData) {
        this.userData.links.push(linkData);
    }
}

Benefits of this one-way binding from top to bottom and the event mechanism:

  • Your parent component can choose to ignore events if it wants - thus making child components reusable in other contexts.
  • Your child components (assuming you have many) will be allowed to send only events upwards, which is easier to debug when compared to each of them directly mutating parent state.

Upvotes: 3

Related Questions