Windows events in iframe - vue.js

I have a Vue application that runs in a iframe of a document. When the user tries to close a iframe, I want to prompt for saving changes. The below code is in my Vue application. The problem is that my parent window starts reacting to these events. Any ideas how this can work only within the iframe?
mounted(){
window.addEventListener('beforeunload', (event) => {
if (this.isDirty() === false)
event.returnValue = `Changes may not be saved. Are you sure you want to leave?`;
});
},
beforeDestroy() {
window.removeEventListener('beforeunload')
},

Related

Can I use Firebase's signinWithRedirect within the dialog API of a MS Powerpoint Add-In on Safari?

I'm developing authentication with firebase for a add-in for MS Powerpoint. In order to add authentication with Google I created a button which opens a dialog box:
`function openGoogleAuthDialog() {
Office.context.ui.displayDialogAsync(hostURLofDialogComponent,
{ width: 50, height: 50 }, (result) => {
if (result.status === Office.AsyncResultStatus.Succeeded) {
dialog = result.value;
dialog.addEventHandler(Office.EventType.DialogMessageReceived, processMessage);
} else {
console.log("Unable to open dialog box");
}
});
}`
The dialog opens successfully. Within the Dialog component i have another button that should redirect to google as well as a useEffect that is supposed to send back the result of the authentication to the parent.
`export function AuthDialog() {
const authFirebase = getAuth(firebaseApp);
const handleAuth = () => {
const provider = new GoogleAuthProvider();
signInWithRedirect(authFirebase, provider);
};
useEffect(() => {
getRedirectResult(authFirebase).then((result) => {
Office.context.ui.messageParent(JSON.stringify(result));
});
}, []);
return <button onClick={handleAuth}>Authenticate With Google</button>;
}`
The problem is, that if I click on the button it will leave the page and it seems like it's gonna redirect but then stops and comes back to the dialog component without showing me the google sign-in interface.
I tried this functionality within google chrome and brave browser and it shows the Google Sign-In Interface as expected. As MS Office Plugins are using Safari under the hood, and the functionality was behaving in the same faulty way in the Safari browser, I can imagine it's a problem with Safari. Has anyone experienced a similar issue? Your help would be much appreciated!

How can I redirect to my home page after a state update in vue.js?

I am working on my first vue project, and am having an issue with the redirect that I want to have happen. My project is a basic to-do app. In my add todo component I have the following function that fires after I submit the form.
methods: {
addTodo:function(e) {
e.preventDefault()
let newTodo = {
title:this.title,
completed: false,
dueDate: new Date(this.date3)
}
console.log(newTodo)
this.$emit('add-todo', newTodo)
window.location.href = '/';
}
}
The event that is emitted then fires up the component tree until it reaches my app.vue file that fires the following method:
addTodo: function (newTodo) {
this.todos = [...this.todos, newTodo]
this.todos = this.todos.sort((a,b) => a.dueDate - b.dueDate)
}
Unfortunately the issue I am having is that my page redirects to my home page from the window.locatio.href method before my app can update state. I have also tried moving window.location.href='/' to the addTodo method in my app.vue file. However I am still facing the same problem. How can I redirect the user only once the new Todo is added to state?
use created(){} after the last},then add window.location.href="/";

Vue: beforeunload event listener is not being removed

I'm working on an undo delete functionality, it consist of a small modal which allows the user to undo/delay the action for a limited amount of time(similar to gmail). However, I want to ensure that the action is executed if the user decides to navigate to another window or close the tab, which I am doing like so:
mounted() {
this.timeout = setTimeout(() => {
this.close(true);
}, this.duration);
window.addEventListener('beforeunload', this.forceDestroyHandler, { capture: true });
},
methods: {
close(deleteBeforeClosing) {
if (deleteBeforeClosing) {
clearTimeout(this.timeout);
// This is the function dispatching to the store and deleting the item
this.destructiveEvent(this.category, this.item.id);
}
this.$emit('close');
}
I am then (attempting) to remove the event listener on beforeDestroy:
beforeDestroy() {
this.forceDestroy();
window.removeEventListener('beforeunload', this.forceDestroyHandler, {capture: true});
},
However, it appears that beforeDestroy is never called, meaning the event listener is never removed - so if the user decides the close the tab or navigate, he is prompted a message even tough the undo component is not even showing anymore. If the user would click on cancel, another action would be dispatched to the store attempting to delete an already deleted item causing an server error.
I also tried to put the removeEventListener elsewhere but I am keep having the same issue.
To further elabourate on my comment: the reason why your onbeforeunload event listener is not unbound is because the beforeDestroy() lifecycle hook is only fired when a VueJS component is destroyed. When you close the browser tab/window, the entire thread is wiped and this does not trigger component destruction.
Since you only want to remove the listener after the modal is closed, it makes sense to do it in the close() method: hence why you approach worked.

Is it possible for Nuxt middleware to wait for asyncData requests to resolve?

I have a some middleware in my Nuxt app that closes a fullscreen mobile menu when a new route is clicked. What I am experiencing is the following:
user clicks nuxt-link
menu closes
asyncData delay (still shows current page)
new page is loaded upon resolved asyncData
What I would like is the following:
user clicks nuxt-link
asyncData delay (if exists)
menu closes upon new page load
Is it possible to have an asyncData watcher in Nuxt middleware?
I know I can hack this by creating a store value that tracks asyncData load, but I'd rather not have to wire up such a messy solution to each and every page that uses asyncData.
Note - not every page uses asyncData.
I think that the best option would be to leave the menu open, and then when the new page finishes loading (probably on the mounted hook) send an event or action to close the menu.
I figured this out in a more elegant solution than having to implement a store.dispatch function on each individual asyncData function.
So what I did was use a custom loading component: https://nuxtjs.org/api/configuration-loading/#using-a-custom-loading-component
However, instead of showing a progress bar or any sort of loading animation, I just used this component to set a loading state in my vuex store. Note - it forces you to have a template, but I just permanently disabled it.
<template>
<div v-if="false"></div>
</template>
<script>
export default {
methods: {
start() {
this.$store.dispatch('updateLoadingStatus', true);
},
finish() {
this.$store.dispatch('updateLoadingStatus', false);
}
}
};
</script>
Then in my middleware, I set up an interval watcher to check when loading has stopped. When stopped, I stop the interval and close the mobile menu.
export default function({ store }) {
if (store.state.page.mobileNav) {
if (store.state.page.loading) {
var watcher = setInterval(() => {
if (!store.state.page.loading) {
store.dispatch('updateMobileNav', false);
clearInterval(watcher);
}
}, 100);
} else {
store.dispatch('updateMobileNav', false);
}
}
}
This doesn't specifically have to be for a mobile menu open/close. It can be used for anything in middleware that needs to wait for asyncData to resolve. Hope this can help anyone in the future!

Onbeforeunload Event calling

I am new to vuejs. Does anyone help me?
If I click the browser refresh button, I need to show the popup. So I used below code here.
I am using the code like,
window.onbeforeunload=function(){
return "Your work will be lost.";
}
I used this function under the beforeMount() lifecycle instance in a single page. But, this popup showed the multiple pages, when I click the browser refresh button. I want to show this pop up in a single page. Can Anyone help me??
I see this is an old post, but maybe this will help you in the future or others. As mentioned above, it would help a lot to see the actual code implementation, but maybe this will help.
<script>
export default {
data: () => ({
shouldPrevent: false
}),
beforeMount() {
window.addEventListener("beforeunload", this.preventNav)
},
beforeDestroy() {
// Don't forget to clean up event listeners
window.removeEventListener("beforeunload", this.preventNav)
},
methods: {
preventNav(e) {
if (!this.shouldPrevent) return
e.preventDefault()
e.returnValue = ""
},
},
}
</script>