If I have a vue template with a vuetify dialog (but really any dialog for that matter), How do I use it to confirm navigation away from the page in vue-router's beforeRouteLeave method?
dialogTest.vue:
<template>
<v-container>
<v-layout>
<v-dialog v-model="dialog" max-width="290" ref="popup">
<v-card>
<v-card-title class="headline">Are you sure you wish to leave this page?</v-card-title>
<v-card-text>Better think long and hard.</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="primary darken-1" flat="flat" @click.native="dialog = false">Nah</v-btn>
<v-btn color="primary darken-1" flat="flat" @click.native="dialog = false">Yah</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</v-layout>
</v-container>
</template>
<script src="./dialogTest.ts"></script>
dialogTest.ts:
import Vue from 'vue';
import { Component } from 'vue-property-decorator';
Component.registerHooks([
'beforeRouteLeave'
]);
@Component
export default class DialogTestComponent extends Vue {
dialog: boolean = false;
beforeRouteLeave(to: Object, from: Object, next: Function) {
console.log('beforeRouteLeave');
//this works, but obviously doesn't use our dialog -> how do we get yah or nah response from dialog instead?
const answer = window.confirm('Do you really want to leave? you have unsaved changes!')
if (answer) {
next()
} else {
next(false)
}
}
}
I like to do this with promises. Give your dialog a pop() method that returns a promise, then resolve the promise with true or false when your user chooses. Or call clickYah() from your unit test. Something like this...
// in your dialog component....
data(){
return {active : false, resolve: null};
}
methods : {
pop(){
this.active = true;
return new Promise(function(resolve, reject){
this.resolve = resolve;
});
},
clickYah(){
this.active = false;
this.resolve(true);
},
clickNah(){
this.active = false;
this.resolve(false);
}
}
// then to call it...
this.$refs.modalDialog.pop()
.then(confirmResult => next(confirmResult));
@bbsimonbb - thanks for the great and quick answer.
Here's my final in ts:
In the parent component (which contains our ConfirmLeaveDialog component with ref="confirmLeavePopup"):
async beforeRouteLeave(to: Object, from: Object, next: Function) {
next(await (this.$refs.confirmLeavePopup as ConfirmLeaveDialog).pop());
}
In the ConfirmLeaveDialog vue class component (I renamed the component's storage of resolve func to be "answer" instead):
import Vue from 'vue';
import { Component, Prop } from 'vue-property-decorator';
@Component
export default class ConfirmLeaveDialog extends Vue {
@Prop({ default: 'Are you sure you wish to leave this page?' })
question: any;
active: boolean = false;
answer: Function = () => { return false }; //. had to provide the type and initialize
pop(): Promise<boolean> {
this.active = true;
return new Promise<boolean>((resolve: Function, reject: Function) => { //. note the arrow function here such that 'this' refers to the component, NOT the calling context
this.answer = resolve;
});
};
confirmLeave(): void {
this.active = false;
this.answer(true);
};
abortLeave(): void {
this.active = false;
this.answer(false);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With