Button gets "out of sync"
Closed this issue · 8 comments
Hello,
I use this button to trigger an offer publication status.
So when I use this button, it calls an API to change the state of the publication.
If an errors occurs, it should revert the button to initial position, except it does not.
Please help me out, thanks.
switchActiveState(offer) {
console.log(offer.active); // returns true in this example
const matchItem = collection.find(this.items, item => item.id === offer.id);
if (matchItem) {
axios
.post('/switch-status....')
.then((response) => {
if (response.data.success === true) {
matchItem.active = response.data.status;
} else {
// if we get anything but success true, we change the value back to initial
matchItem.active = offer.active;
}
})
.catch(() => {
// if we get any error, we change the value back to initial
matchItem.active = offer.active;
})
;
}
},
<template slot="status" slot-scope="slotProps">
<toggle-button
@change="switchActiveState(slotProps.item)"
:value="slotProps.item.active"
color="#20aec4"
:sync="true"
:labels="false"
/>
</template>
Result in screenshot, after clicking, the active
on the object is still true, because there were an error:
BUT the button is "false" instead of true as if the offer is not published.
What am I missing there ?
I wanted to ask the same question. I find the same problem and I don't know why :(
try caching offer.active
rather than directly using it by reference.
Mhh, not sure If I understand you correctly, I tried:
switchActiveState(offer) {
console.log(offer, offer.active);
const matchItem = collection.find(this.items, item => item.id === offer.id);
if (matchItem) {
axios
.post(this.getSwitchRouteFor(offer))
.then((response) => {
if (response.data.success === true) {
offer.active = response.data.active;
} else {
offer.active = offer.active;
}
})
.catch(() => {
offer.active = offer.active;
})
;
}
},
Without any difference.
When it fails, the switch-button still act as if everything were normal, and it's not reverting
Try this out of interest:
switchActiveState: offer => {
const cachedActive = offer.active
const matchItem = collection.find(this.items, item => item.id === offer.id)
if (matchItem) {
axios
.post('/switch-status....')
.then(response => {
if (response.data.success) {
matchItem.active = response.data.status
} else {
matchItem.active = cachedActive
}
})
.catch(() => {
matchItem.active = cachedActive
})
}
},
When trying your version, it gives:
[Vue warn]: Error in event handler for "change": "TypeError: undefined has no properties"
And when trying to fix it by putting :
switchActiveState(offer) {
It's the same behaviour like before. Even when I do this:
switchActiveState(offer) {
offer.active = true;
}
or
switchActiveState(offer) {
const matchItem = collection.find(this.items, item => item.id === offer.id);
matchItem.active = true;
}
The button still act on it's on toggling on and off instead of being forced to be "on" all the time. (because of the .active = true
)
@euvl Full code can be found here if it helps you understand what's wrong, it's the <toogle-button>
on L58
that i'm reffering to.
https://gist.github.com/tristanbes/bf3ff71f4c091693382f05abfdd9eea5
thanks to @Kocal, the working example is:
switchActiveState(offer) {
const wasActive = offer.active;
offer.active = !wasActive;
this.$set(offer, 'toggling', true);
axios
.post(this.getSwitchRouteFor(offer))
.then((response) => {
offer.active = response.data.success === true ? response.data.active : wasActive;
})
.catch(() => {
offer.active = wasActive;
})
.finally(() => {
this.$delete(offer, 'toggling');
});
},
I just get the same problem and fixed it.
If you use it inside looping, you should add prop :key
to the toggle button