0
votes

ive seen afew answers that sort of answer my question but not fully, so let me explain what I want to do.

We use a global #app div within the layout of our website, which is a Laravel project. So all pages will be the same main Vue instance, due to this i'm separating key functionality into components.

So, the first example is just a simple Tab component, this either separates any children into tabs, or accepts some data which the single child component then renders.

So below i'm injecting some data from another component, this ajax component literally just does an ajax call, and makes the data available within it's slot.

<ajax endpoint="/api/website/{{ $website->id }}/locations/{{ $location->slug }}/get-addresses">
    <div>
        <tabs :injected="data">
            <div>
                <div v-for="row in data">
                    @{{ row['example' }}
                </div>
            </div>
        </tabs>
    </div>
</ajax>

Now this is all well and good, to a point, but this falls down with the below code. This contains a component which will allow the used to drag and drop elements, it re-arranges them by literally moving the data around and letting Vue handle the DOM changes.

This will of course work fine within it's own data which you have injected in, but when you change the data within the component below this then clears this child component.

<ajax endpoint="/api/website/{{ $website->id }}/locations/{{ $location->slug }}/get-addresses">
    <div>
        <tabs :injected="data">
            <div>
                <div v-for="row in data">
                    <draggable :injected="row">
                        <div>
                            <div v-for="item">
                                @{{ item }}
                            </div>
                        </div>
                    </draggable>
                </div>
            </div>
        </tabs>
    </div>
</ajax>

I need to find a way to make any changes to this data apply to the parent data, rather than the data passed into the child components.

What is the best practice to do this!?


Edit 1

Basically, I need any child component's manipulate the data within the ajax component. The children within ajax could change, or there could be more, so I just need them all to do this without knowing what order or where they are.

1
I would love to help you, but I do not get the question. What are you trying to accomplish exactly? Which component does what? Where is the data? Maybe posting the component code together with the data and method attributes would help?Imre_G
@Imre_G Made an editMartyn Ball
I suspect you need a :key in your v-for.Roy J
@MartynBall it already looked familiar, but didn't you pose a similar question two days ago? Where did you get stuck?Imre_G
@Imre_G I think I might of asked a similar question. I'm basically having issues with my data going into multiple components. Like I say in the question above, if I keep passing this data into props, and then change that data within the prop, this won't update the original data, so any additional changes may re-render the child component and I will loose the changes!Martyn Ball

1 Answers

1
votes

It is hard to come up with specifics on this one, but I am going to try to put you in the right direction. There are three ways to share data between components.

1) Passing down data via props, emitting data up via custom events

The passing down of data via props is a one-way street between the parent and child components. Rerendering the parent component will also re-render the child and data will be reset to the original state. See VueJS: Change data within child component and update parent's data.

2) Using a global event-bus

Here you create an event bus and use this to emit the data to different components. All components can subscribe to updates from the event bus and update their local state accordingly. You initiate an event bus like this:

import Vue from 'vue';
export const EventBus = new Vue();

You send events like this:

import { EventBus } from './eventbus.js'
EventBus.$emit('myAwsomeEvent', payload)

And you subscribe to events like this:

import { EventBus } from './eventbus.js'
EventBus.$on('myAwsomeEvent', () => {
  console.log('event received)
})

You still need to manage state in the components individually. This is a good start with an Event bus: https://alligator.io/vuejs/global-event-bus/

3) Using Vuex

Using Vuex extracts the component state into the Vuex store. Here you can store global state and mutate this state by committing mutations. You can even do this asynchonously by using actions. I think this is what you need, because your global state is external to any components you might use.

export const state = () => ({
    resultOfAjaxCall: {}
})

export const mutations = {
    updateAjax (state, payload) {
        state.resultOfAjaxCall = payload
    }
}

export const actions= {
    callAjax ({commit}) {
        const ajax = awaitAjax
        commit('updateAjax', ajax)
    }
}

Using vuex you keep your ajax results separated from your components structure. You can then populate your state with the ajax results and mutate the state from your individual components. This way, it doesn't matter whether you recall ajax, or destroy components since the state will always be there. I think this is what you need. More info on Vuex here: https://vuex.vuejs.org/