1
votes

not sure i'm going about this the correct or best way.

Basically I have got the following data:

surrounding: {
    data: [
        { id: 1, name: 'test' },
        { id: 2, name: 'test' },
        { id: 3, name: 'test' }
    ],
    loading: false
}
editingLocation: {
    id: 1,
    name: 'location 1',
    surrounding: [ 1, 2 ]
}

This data is within Locations component, I have then got another component (Surrounding) which will manipulate this data, my Locations component only needs to keep editingLocation in sync so when you assign a surrounding it updates the array.

export default {
        props: {
            editingLocation: {
                type: Object,
                default: () => { return {} }
            },
            surrounding: {
                type: Object,
                default: () => { return {} }
            }
        }

My issue is within Surrounding component I have the ability to add a new surrounding and to delete a surrounding. Which then of course needs to update the Surrounding component AND the Locations component, but of course if you delete one a loop is needed to remove the ID from all the locations with that ID within the array.

toggle: function(item) {
    const self = this;

    item.saving = true;

    Axios.post("endpoint", item).then(response => {

        item.saving = false;

        /**
         * Success
         */
        if (response.status === 200 && (response.data.attached && response.data.detached)) {
            if (response.data.attached.length) {
                this.editingLocation.surrounding.push(item.id);
            }

            if (response.data.detached.length) {
                let index = this.editingLocation.surrounding.indexOf(item.id);
                if (index > -1) {
                    this.editingLocation.surrounding.splice(index, 1);
                }
            }

            return;
        }

As you can see the toggle method toggles the prop editingLocation, but of course this doesn't get passed back to my Locations component because it's a prop.

My second issue is when I delete a surrounding, I need to remove this from all the locations within my Locations component:

Axios.post("endpoint", item).then(response => {

    if (response.status === 200) {
        item.deleting = false;

        if (response.data.success) {

            let index = this.surrounding.data.map(function(e) {
                return e.id;
            }).indexOf(item.id);
            let locationIndex = this.editingLocation.surrounding.indexOf(item.id);

            this.surrounding.data.splice(index, 1);
            this.editingLocation.surrounding.splice(locationIndex, 1);

            self.$emit('surrounding-removed', item.id);
        }

This is how I pass the data to my Surrounding component:

<legacy-surrounding-locations :editing-location="editing"
                              :surrounding="surrounding"
                              :locations="locations"
                              @surrounding-removed="deletedSurrounding($event)"
                              @close="surroundingDisplay = false"></legacy-surrounding-locations>

And this is the deletedSurrounding method I have at the moment:

deletedSurrounding: function(id) {
    Object.keys(this.locations.data).forEach(key => {
        let index = this.locations.data[key].surrounding.indexOf(id);
        if (index > -1) {
            this.locations.data[key].surrounding.splice(index, 1);
        }
    });
}

Can someone help me out with this logic to get it right and the best way to go about doing this?

1

1 Answers

1
votes

Usually the simplest approach in this situation is to think of component communication in this way: Parent components pass state to their children via props, and children can communicate changes back up to parents via events.

The Vue documentation has pretty solid examples on this here.


In general what I would do is make your <Surrounding /> component trigger an event for both attaching and detaching to it's location, passing in the needed data only and then the parent component, <Locations /> in this case, would do the actual heavy lifting like what you wrote here:

if (response.data.attached.length) {
    this.editingLocation.surrounding.push(item.id);
}

if (response.data.detached.length) {
    let index = this.editingLocation.surrounding.indexOf(item.id);
    if (index > -1) {
        this.editingLocation.surrounding.splice(index, 1);
    }
}

And since <Locations /> is passing this state down to <Surrounding /> via props, it would be updated immediately.


Unless of course these two components aren't in a Parent/Child relationship in which case you either need to lift the state up to a higher component or consider using some sort of global state solution - such as Vuex. But that's overkill if these components are setup in a simple Parent/Child relation.