Martyn Ball
Martyn Ball

Reputation: 4895

VueJS: Change data within child component and update parent's data.

I'm using multiple components together, so that then can be re-used. The main component does an aJax call to fetch some data, then this get's passed down to another component, then again this data will be passed to another component.

<input-clone endpoint="/api/website/{{ $website->id }}/locations/{{ $location->slug }}/get-business-hours" name="businessHours">

    <div class="input-clone businessHours" slot-scope="{ data, add, remove, onDragStart, onDragEnd, onDragOver, onDragEnter, onDragLeave, onDrop, setClass }">

        <business-hours :injected-data="hours" :injected-days="data.days[0]">

            <time-select :injected-data="hours.open_time" :key="'opentime' + hoursIndex">

            </time-select>

        </business-hours>

    </div>

</input-clone>

The main issue is that the input-clone component has a drag and drop feature, which lets me move the items inside around, when it moves them it rearranges the main data object, which of course re-renders the child components, so any data changes within the children is reset.

How can I update the main data from the children so when I rearrange the elements they don't loose the data changes.

Upvotes: 0

Views: 2970

Answers (3)

Ealhad
Ealhad

Reputation: 2240

Implement v-model for your component.

From the Vue documentation:

For this to actually work though, the inside the component must:

  • Bind the value attribute to a value prop
  • On input, emit its own custom input event with the new value

In code, this translates as:

props: ['value']

in your component declaration, and calling

this.$emit('input', <something>)

to update the value.

Upvotes: 0

Imre_G
Imre_G

Reputation: 2535

You are looking for $emit. In the child component emit the data changes to the parent by using $emit('updateData', payload). You can then listen for the update on the component, for example like this:

<business-hours @updateData="doSomething(payload)" :injected-data="hours" :injected-days="data.days[0]">

You can use the doSomething method to update your main data with the changes from the component. This way they will be kept when the components are rerendered.

More info here: https://v2.vuejs.org/v2/guide/components.html#Emitting-a-Value-With-an-Event

Upvotes: 2

front_end_dev
front_end_dev

Reputation: 2056

Instead of changing the data into the child component first then update the parent component what you should do emit the event on the parent component about the change in child component and set the state in parent component then child component will re-render by that. In this way you maintain the philosophy of parent child component that parent should pass data into child and child notify parent of any change.

You can read more about it in this blog post - https://medium.com/@sky790312/about-vue-2-parent-to-child-props-af3b5bb59829

Upvotes: 1

Related Questions