2👍
You could use a beforeRouteLeave
navigation guard to abort that action (i.e., cancel the timer in your example) upon switching routes.
- Assuming identifiable submit actions, save the ID of the operation result (i.e., save the timer ID from
setTimeout
‘s return value in your example). - Add a
beforeRouteLeave
handler to the component to cancel the submit action (i.e., clear the timer ID in your example).
const Home = {
methods: {
submit() {
this.timerId /* 1 */ = setTimeout(() => {
this.$router.push("/bar");
}, 5000);
}
},
beforeRouteLeave (to, from, next) {
clearTimeout(this.timerId) /* 2 */
next()
}
};
1👍
Here’s one idea: make a component that provides (using Vue’s provide
/inject
API):
- A function that starts an operation. This is called when a form is sent. It provides a
whenDone
callback which is either executed or ignored, depending on if the operation is cancelled. - A function that cancels all pending operations. The cancel function could be called when the user navigates away.
The implementation could look like this:
const CancellableOperationProvider = {
name: "CancellableOperationProvider",
props: {},
data: () => ({
pendingOperations: []
}),
/*
* Here we provide the theme and colorMode we received
* from the props
*/
provide() {
return {
$addOperation(func) {
this.pendingOperations.push(func);
func(function whenDone(callback) {
if (this.pendingOperations.includes(func)) callback();
});
},
$cancelAllOperations() {
this.pendingOperations = [];
}
};
},
render() {
return this.$slots.default[0];
}
};
The usage would look like this:
const Home = {
template: '<div><button @click="submit">Save and go Bar!</button></div>',
inject: ['$addOperation', '$cancelAllOperations'],
methods: {
async submit() {
this.$addOperation(whenDone => {
await setTimeout(() => {
whenDone(() => this.$router.push("/bar"));
}, 5000);
});
}
}
};
You could then add a navigation guard to the Vue Router so that $cancelAllOperations
is called after clicking any link. Since $cancelAllOperations
is only accessible through the inject
API you will have to make a component that imperatively adds a navigation guard to the Vue router after mounting and removes it when unmounting.
Let me know if it doesn’t work–I haven’t done Vue in a while.
0👍
I used the answer from tony19 to make solution which fits my needs for use cases without setTimeout too:
const Home = {
template: '<div><button @click="submit">Save and go Bar!</button></div>',
data() {
return {
onThisPage: true
}
},
beforeRouteLeave(to, from, next) {
this.onThisPage = false;
next();
},
methods: {
submit() {
setTimeout(() => {
if (this.onThisPage) {
this.$router.push("/bar");
}
}, 5000);
}
}
};
See here: https://jsfiddle.net/ovmse1jg/