Onbeforeunload Event calling - vue.js

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>

Related

Windows events in iframe

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')
},

How do I display the captcha icon only on certain pages (VUE reCAPTCHA-v3)?

I use this package : https://www.npmjs.com/package/vue-recaptcha-v3
I add on my main.js :
import { VueReCaptcha } from 'vue-recaptcha-v3'
Vue.use(VueReCaptcha, { siteKey: 'xxxxxxx' })
I add this code :
await this.$recaptcha('login').then((token) => {
recaptcha = token
})
to my component to get token from google recapchta
My problem is the captcha icon in the lower right corner appears on all pages
I want it to only appear in certain components
Maybe I must to change this : Vue.use(VueReCaptcha, { siteKey: 'xxxxxxxxxxxxxxxxx' }). Seems it still mounting to Vue.use. I want to mount to a certain component instead of vue root instance
How can I solve this problem?
Update
I try like this :
Vue.use(VueReCaptcha, {
siteKey: 'xxxxxxx',
loaderOptions: {
useRecaptchaNet: true,
autoHideBadge: true
}
})
It hides the badge. I want the badge to still appear. But only on 1 page, the registration page. How can I do it?
I've had the same issue while using the npm package, it's pretty annoying.
At the end of the day, I've decided not to use the package & follow Google's documentation.
This line here :
grecaptcha.execute('_reCAPTCHA_site_key_', {action: 'login'}).then(function(token) {
recaptcha = token
})
Is equivalent to this line here from the npm package :
this.$recaptcha('login').then((token) => {
recaptcha = token
})
You just need to add this line into your < head > for recaptcha to work :
<script src="https://www.google.com/recaptcha/api.js?render=_reCAPTCHA_site_key"></script>
But as soon the script tag is in your < head >, you will be facing the same issue of it showing on every page.
The hack is that you only insert it into the < head > on components that you need.
There are ways to do this but I ended up referencing this.
You can put it in the methods of your component & call the method when the component is loaded.
That way it will only show up on the pages that you need it to.
in main.js set autoHideBadge true:
import { VueReCaptcha } from 'vue-recaptcha-v3'
Vue.use(VueReCaptcha, { siteKey: 'your site key',
loaderOptions:{autoHideBadge: true }})
in every page you want to show the badge you can show the badge in mounted,
for some reasons until a few seconds after mounted event this.$recaptchaInstance is null and you cant use it, so I use a timeout to showing the badge 5 second after page load in mounted.
mounted(){
setTimeout(()=>{
const recaptcha = this.$recaptchaInstance
recaptcha.showBadge()
},5000)
},
when you show it you have to hide it again in the same page.
beforeDestroy() {
const recaptcha = this.$recaptchaInstance
recaptcha.hideBadge()
},
If you are using composition API setup this is what you need:
const reCaptchaIn = useReCaptcha().instance
onMounted(() => {
setTimeout(() => {
reCaptchaIn.value.showBadge()
}, 3000)
})
Just use this code:
const recaptcha = this.$recaptchaInstance
// Hide reCAPTCHA badge:
recaptcha.value.hideBadge()
// Show reCAPTCHA badge:
recaptcha.value.showBadge()
vue-recaptcha-v3 npm
I stumbled upon this incredibly simple answer. It is excellent especially if you wish to hide the badge from all your pages. You can perhaps use scoped css to hide on some pages as well.
.grecaptcha-badge { visibility: hidden; }
You can read the post here

Vuejs not refreshing the component after redirection

I have a form in one component. After the submit-ion i am redirecting the view to the list where new submit should display.
But is doesn't.
I have to refresh the page and then the change will appear.
How do I instruct the page to reload the content after it is updated
Currently, in order to change the route, I am using:
methods: {
submitMovie () {
movieService.submitMovie(this.newMovie)
.then( this.$router.push('/movies'))
.catch( e=> { this.errors.push(e) })
}
.then(() => { this.$router.push('/movies') })
Thanks Phill.
I was trying to solve this for about 2 days.
All it needed was a function inside next.
Why I still don't understand but I will research about the issue
Thanks Again

Page reload causes Vuex getter to return undefined

Using Vue.js (Vuetify for FE).
A page reload causes the getter in Vuex to fail with pulling required data from the store. The getter returns undefined. The code can be found on GitHub at: https://github.com/tineich/timmyskittys/tree/master/src
Please see the full details on this issue at timmyskittys.netlify.com/stage1. This page has complete info on the issue and instructions on how to view the issue.
Note, there is mention of www.timmyskittys.com in the issue description. This is the main site. timmyskittys.netlify.com is my test site. So, they are the same for all intents and purposes. But, my demo of this issue is at the Netlify site.
I read the complete issue in the website you mentioned. It's a generic case.
Say, for cat details page url: www.timmyskittys.com/stage2/:id.
Now in Per-Route Guard beforeEnter() you can set the cat-id in store. Then from your component call the api using the cat-id (read from getters)
I found the solution to my issue:
I had to move the call of the action which calls the mutation that loads the .json file (dbdata.json) into a computed() within App.vue. This was originally done in Stage1.vue.
Thanks all for responding.
I had the same issue and my "fix" if it can be called that was to make a timer, so to give the store time to get things right, like so:
<v-treeview
:items="items"
:load-children="setChildren"
/>
</template>
<script>
import { mapGetters } from 'vuex'
const pause = ms => new Promise(resolve => setTimeout(resolve, ms))
export default {
data () {
return {
children: []
}
},
computed: {
...mapGetters('app', ['services']),
items () {
return [{
id: 0,
name: 'Services',
children: this.children
}]
}
},
methods: {
async setChildren () {
await pause(1000)
this.children.push(...this.services)
}
}
}
</script>
Even though this is far from ideal, it works.

VueJS show splash screen after login (different landing page)

I have my VueJS application in which the user logins and depending on the role a specific landing page is pushed in the router.
Here the sample code or the store that handles login:
login({ dispatch, commit, state }, data) {
return API.post('api/account/login', data).then(({ data }) => {
if (data.success) {
var view = getView(data.data, state)
router.push(view);
}
return Promise.resolve(data);
});
},
So as you can see I can have different landing pages after login depending on user role. What I need to do is that no matter what landing page is I have to show a Splash screen (modal) after the user logins.
If its only one landing page for all I guess I could add something in the mount event of that view to show the modal, but because I have 9 different landing views I dont think the best way is to add the same code to the 9 views.
Is there a way I can do that in a propper or best practice way?
Thanks
If you have 9 different routes a user can be directed to, could you:
create a modal component
load it into these views/routes
open it when the route is mounted
This way the modal code is centralized in its own component, and can watch for a property change to appear.
As a followup on my comment: you can mount a separate Vue instance. You can do it with something like this:
createNewInstance: function(){
const splash = new Vue({
methods: {
closeHandler() {
return function() {
splash.$destroy();
splash.$el.remove();
};
}
},
render(h) {
return h(YourSplashComponent, {
mounted() {
setTimeout(this.closeHandler(), 3000)
}
});
}
}).$mount();
document.body.appendChild(splash.$el);
}
Just be sure to import and create a component on where YourSplashComponent is stated in the example.
Call the function right before you do trigger your route