proper vueJS way to sync props with data

10,065

You have three (at least) ways of doing it:

1) Connect the data via the prop attribute, just as you are doing, but add the .sync attribute to it. This way, when the data is modified on the form, it automatically gets modified too on the component. The problem with this solution is that the update is automatic, so if a validation fails, or the user closes the modal without saving the changes, these are saved anyway. An example: https://jsfiddle.net/Lz3aq64f/

2) The other way of doing it is getting the modal to $dispatch an event with the saved information when it's saved. The blogpost element should listen for this event and act accordingly.

On the modal:

this.$dispatch('update-post', this.title, this.author);

On the blogpost:

this.$on('update-post', function(title, author) {
  this.title = title;
  this.author = author
});

If the blogpost component and the modal component are not in the same hierarchy, things get a little bit more complicated, and probably you need the common parent element to act as a proxy. Think of the modal element dispatching the information up, the #app element catching it via $on, and then doing $broadcast to the blogpost element.

3) Use something like vuex to act as a central repository of state. I don't know how big is your application, but this would be the cleanest way to go: http://vuex.vuejs.org/en/index.html

Good luck!

Share:
10,065

Related videos on Youtube

Geert-Jan
Author by

Geert-Jan

Updated on June 04, 2022

Comments

  • Geert-Jan
    Geert-Jan almost 2 years

    Consider a VueJS app that allows for showing / editing blogposts.

    • On clicking "edit blogpost" a modal (Vue component) is shown to edit the current blogpost (just an ordinary js-object).
    • To this end I pass the current blogpost as a prop to the modal-component.
    • The Modal component has a couple of form fields that should be populated with the blogpost-attributes.
    • However, the Vue 'way' is to have a data object on the Modal-component that acts as the model to populate the form fields, and vice-versa, be updated when the user changes the form fields.

    The problem: How do I connect the blogpost which is passed as a prop to the data field of the modal-component so that:

    • the blogpost populates the form fields
    • the blogpost gets updated when updating the form fields

    What's the correct Vue way to accomplish this?

  • Geert-Jan
    Geert-Jan over 7 years
    Came up with an option 4 (based on gitter vuejs chat) which seems to work. This is based on realization that all props are automatically part of data (no need for sync here) Therefore if I have a prop called blogpost (a plain object), I could just use blogpost in the component template like so <input type="text" v-model="blogpost.title">. This with the same caveat as your option 1, in that updates are done immediately, so I need to make sure to keep a blogpostOld around or something to merge back in on cancel. Thanks for the great overview.
  • Hector Lorenzo
    Hector Lorenzo over 7 years
    Yes, props, data and computed share similar qualities. BUT, as far as I understand, though, when you pass a prop to an item, the relation is one-way-down (a change in the parent is passed to the children). If you use .sync, the relation becomes two-way: a change of data in the child also changes the parent: vuejs.org/guide/components.html#Prop-Binding-Types
  • Geert-Jan
    Geert-Jan over 7 years
    Definitely seeing the intended two-way behavior without defining sync. I'm guessing this is because I'm passing an object reference instead of a simple type like string.
  • Peter Chaula
    Peter Chaula almost 7 years
    $dispatch was removed in the latest versions of vue