In documentation, deviceBackButton is fired on device back button. It isn't fired on device back button in my application.
Device back button terminates my application without showing alert dialog. I don't want to terminate app.
<template>
<v-ons-alert-dialog
#deviceBackButton="backButtonEvent"
>
...
</v-ons-alert-dialog>
</template>
<script>
export default {
methods: {
backButtonEvent(event) {
alert('hello, world');
return event.preventDefault();
}
}
}
</script>
This is due to a bug in Onsen UI.
The bug has now been fixed but not released yet:
https://github.com/OnsenUI/OnsenUI/commit/f55de7910
It will be included in the next patch release of Onsen UI.
So to answer your question, you can make sure the deviceBackButton handler is called by building Onsen UI from master and using that in your project, or you can use the next version when it is released.
Related
Currently I create a html5 video player component for an universal nuxtjs/vuejs app.
There is an autoplay attribute for the video tag to start videos after navigate to them.
Usually browsers don't do that directly after page load, it's prohibited.
I need a variable in my component to know if autoplay will be possible to style elements based on this information.
In other words: The variable should be true if the current page was only rendered on client-side, but false if it was rendered on server-side first.
It's not possible to work with "window.history.length" because the autoplay will also not be possible after refresh, although this would not have an effect on the history length.
Also it's not possible to set a variable in the "created" method since it will be called on server- and client-side too.
In nuxt - there is the <client-only> component that renders components only on the client side
<template>
<div>
<sidebar />
<client-only placeholder="Loading...">
<!-- this component will only be rendered on client-side -->
<comments />
</client-only>
</div>
</template>
In nuxt, there are is asyncData which is run beforeCreate(), i.e. you can retrieve data from the server side in asyncData before the component is mounted.
Alternatively, you can check on the created() for the process, e.g.
created() {
if (process.client) {
// handle client side
}
}
edit
https://stackoverflow.com/a/53058870/2312051
Audio.play() returns a Promise which is resolved when playback has been successfully started. Failure to begin playback for any reason, such as permission issues, result in the promise being rejected.
const playedPromise = video.play();
if (playedPromise) {
playedPromise.catch((e) => {
if (e.name === 'NotAllowedError' ||
e.name === 'NotSupportedError') {
//console.log(e.name);
}
});
}
In your case, looks like your browser/os does not allow automatic playing of audio. The user agent (browser) or operating system doesn't allow playback of media in the current context or situation. This may happen, for example, if the browser requires the user to explicitly start media playback by clicking a "play" button. Here is the reference.
One possible solution would be to get the length of the Vue router entries. This seems currently not to be possible without manually tracking. So I ended with this code in my layout component:
watch: {
$route () {
Vue.prototype.$navigated = true
}
}
The value of $navigated is undefined or true and so I know in the layout children components if video autoplay is possible or not.
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.
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!
How can I execute animations upon navigating (via $router) to and from a page/url. Ie, how can I perform animations on show and on leave of a page? I will have different enter and leave animations for each page. The animations are complex thus we use javascript callbacks instead of css3 implementation
I have attempted the following but the transition callbacks dont fire every time. For some pages the callbacks fire for others they dont and they all have the exact code. It's quite weird.
Example MyPage.vue (could be Contact.vue, AboutUs.vue etc.):
<template>
<transition v-on:enter="enter" v-on:leave="leave">
<main>
<p>Foo</p>
</main>
</transition>
</template>
<script type="text/javascript">
import gsap from 'gsap' // include animation library
export default {
methods: {
enter: function (el, done) {
// I only see the text enter sometimes for a page. Its not consistently firing
console.log('enter')
done()
},
leave: function (el, done) {
// I only see the text leave sometimes for a page. Its not consistently firing
console.log('leave')
done()
}
}
}
</script>
Check this example : https://codesandbox.io/s/n38vz0pnzp
It's triggering as expected.
I added the appear prop which triggers the enter animation even for the first component mounting (when starting the app).
I'm creating an app visually similar to Alfred to manage and search for my bookmarks. Its working well, but when I do a search and open a bookmark, I immediately hide the app and when I invoke it again, it return to the default mode doing a visual flash. The reset to default is triggered right before hiding the app.
I hide the application like this : remote.app.hide() and I added a listener on win.hide in my components to reset the vue.
It works, but the reset is processed after the application show up again.
I don't know how to do it when the application is hide or to show up it right after the vue is reloaded.
If you have any clue, it would be great.
I created a sample project on Github you can clone and test this issue.
Github Project
I'm working on macOS at the moment.
Thank you.
I found an easy way, you cannot rely on the window.on('hide') event.
So in your shortcut registration, I made your app emit a custom event that your Vue.js will listen to reset your input before hiding the app:
main.js
const retShow = globalShortcut.register('CmdOrCtrl+Alt+V', () => {
if (!win.isVisible()) {
win.show()
} else {
app.emit('hide-window'); // Let the window hide the app
}
})
In your Vue.js app, in the created hook:
app.js
app.on('hide-window', function () {
vm.reset();
setTimeout(app.hide, 10);
});
Here my pull request: https://github.com/Cronos87/electron-vue-flash-issue/pull/1/files