Nuxtjs auto log out user inactive - vue.js

I'm using Nuxtjs for my project. I need to logout the user if there is not active after a given time frame. I'm creating a new component name autologout.vue and add this code to it
autologout.vue
<template>
<div>
hello
<div v-if="warningZone">warning</div>
</div>
</template>
<script>
export default {
data() {
return {
events: ['click', 'mousemove', 'mousedown', 'scroll', 'keypress', 'load'],
warningTimer: null,
logoutTimer: null,
warningZone: false,
}
},
mounted() {
this.events.forEach(function (event) {
window.addEventListener(event, this.resetTimer())
}, this)
this.setTimers()
},
destroyed() {
this.events.forEach(function (event) {
window.removeEventListener(event, this.resetTimer())
}, this)
this.resetTimer()
},
methods: {
setTimers() {
this.warningTimer = setTimeout(this.warningMessage(), 4 * 1000)
this.logoutTimer = setTimeout(this.logoutuser(), 10 * 1000)
this.warningZone = false
},
warningMessage() {
this.warningZone = true
},
logoutuser() {
this.$auth.logout('local').then((data) => {
console.log(data)
})
},
resetTimer() {
clearTimeout(this.warningTimer)
clearTimeout(this.logoutTimer)
this.setTimers()
},
},
}
</script>
<style></style>
add import this component to layout->default.vue. I'm not using default.vue layout to my login page. after I'm login and redirect to the home page it always logout me. What is wrong?
I'm using this tutorial to implement this
Tutorial link

Although it is not a perfect way to handle the problem, but if you remove the parentheses present inside the addEventListener function, it will start working.
Change
window.addEventListener(event, this.resetTimer())
To
window.addEventListener(event, this.resetTimer)
And if you remove the paratheses from removeEventListener, it will again stop working. Don't know why.

Related

nuxt buefy filter is not working in taginput field

I am using buefy taginput in my form, everything works as expect filter using ontype event.
only problem here is that i can see data in taginput box on when i focus, its getting selected too, but when i type its not getting filtered. for 10-15 items its not a problem but when its 1000+ items, it will be difficult. i don't know whats the problem here.
here is code so far.
<template>
<b-field label="Popular Destinations">
<b-taginput
v-model="form.popularSubDests"
:data="allSubDests"
autocomplete
:allow-new="allowNew"
:open-on-focus="openOnFocus"
field="SubDestName"
icon="label"
placeholder="Add Cities"
#typing="getFilteredSubdest"
>
</b-taginput>
</b-field>
</template>
<script>
export default {
data() {
return {
openOnFocus: false,
isSelectOnly: false,
allowNew: false,
allSubDestinations: [],
form: {
popularSubDests: [
{
SubDestName: null,
SubDestId: null,
},
],
},
}
},
computed: {
allSubDests() {
return this.allSubDestinations.map((item) => ({
SubDestId: item.id,
SubDestName: item.subdestname,
}))
},
},
methods: {
getFilteredSubdest(text) {
this.allSubDests = this.allSubDests.filter((option) => {
return option.SubDestName.toString().toLowerCase().indexOf(text.toLowerCase()) >= 0
})
},
},
async asyncdata({ route }) {
let { data: allSubDest } = await axios.get(`process.env.FETCHSUBDEST`)
return {
allSubDestinations: allSubDest.results,
}
},
}
</script>

Why currentPage does not do anything in Vue

I am creating a paginator it does not display any error but when I click in the button 1 or 2 or 3 etc, it does not do anything so I wonder why not.
My component template code:
<v-pagination v-model="currentPage"
:page-count="total"
:classes="bootstrapPaginationClasses"
:labels="paginationAnchorTexts"
></v-pagination>
My script code:
export default {
created() {
this.getPosts();
},
methods: {
getPosts() {
fetch('/api/bank?page='+this.currentPage)
.then(response => response.json() )
.then(
json => {
this.posts = json.data.data;
this.total = json.data.last_page;
this.currentPage = json.data.current_page;
});
}
},
components: { vPagination },
data: function() {
return {
postsSelected: "",
posts: [],
currentPage: 1,
total: 0,
bootstrapPaginationClasses: {
ul: 'pagination',
li: 'page-item',
liActive: 'active',
liDisable: 'disabled',
button: 'page-link'
},
paginationAnchorTexts: {
first: 'Primera',
prev: '«',
next: '»',
last: 'Última'
}
}
}
}
So if I have in the function getPosts(); the value this.currentPage it automaticly will send the current page, but when I click in 1 or 2 or 3 etc nothing happens, it just display 1 and nothing else, it does not display 1 several times just one time, so I think that I miss something which it fires something that it notifies that I am pushing the paginator button.
what do I miss?
Thanks!
Because you do nothing when currentPage change. You can listen on input event and then call getPosts.
Example:
<v-pagination
v-model="page"
#input='getPosts'>
</v-pagination>
JSFiddle

Show HTML content with events, loaded from the backend in Vue template

I need to show an image and HTML content with events in the template.
The HTML of the template comes in part from the backend and I need to do a treatment on the front end.
I need to put an image in the new HTML.
I'm doing it this way, but it doesn't work.
The image is always empty.
<template>
<div
v-html="resultado"
></div>
</>
data: ()=>({
resultado:null
}),
mounted(){
fillElement();
},
computed:{
getImage() {
return require("#/assets/pdf.png");
},
},
methods:{
fillElement(){
//get html from backend
const ohtml=getHtmlFrmBackEnd();
let p1 = `<div>Image<img :src='getImage()'></img>${ohtml}</div>`;
this.resultado = p1;
},
}
Solution:
<template>
<div>
<component :is="resultado"></component>
</div>
</template>
<script>
import Vue from "vue";
export default {
data: () => {
return {
resultado: null
};
},
computed: {
compiledData() {
return {
resultado: null
};
}
},
methods: {
delay() {
//making a backend call
return new Promise(resolve => {
setTimeout(() => {
resolve(
"<input type='button' name='btnVoltar' id='btnVoltar' value=' Voltar ' class='button' v-on:click='fVoltar()'>"
);
}, 1000);
});
},
replace(content) {
this.resultado = Vue.component("template-from-server", {
template: content,
methods: {
fVoltar() {
console.log("click");
}
}
});
},
async fillElement() {
//get html from backend
const ohtml = await this.delay();
let p1 = `<div>Image<img src='${require("#/assets/logo.png")}'></img>${ohtml}</div>`;
this.replace(p1);
}
},
mounted() {
this.fillElement();
}
};
</script>
Working Code Example
You can see I loaded the image directly into the src and called fillElement() with this keyword in the mounted() hook.
I also added a delay function to demonstrate a request to the backend.
Edit:
In order to handle events coming with the template from the backend, I created a mini component within the current component that will get rendered once the content is passed. For that, I had to locally import Vue.
Please keep in mind that you will need to replace onclick with #click or v-on:click. You can use regex for that as you have done so already.

Watch $route.params.id does not trigger re-render of Vue component

I have a Post component which displays user posts. The URL/Route to get to a post is like:
http://localhost:8080/123-todays-bike-ride with 123 being the PostID param in the route.
In my Post.vue component I have the following code:
<template>
<div>
<h1>{{Post.PostTitle}}</h1>
<p>{{Post.Content}}</p>
</div>
</template>
<script>
export default {
name: "Post",
watch:{
'$route.params.PostID': function() {
this.getPost(); // does not seem to be triggered?
}
},
computed:
{
Post() {
return this.$store.getters.getPost
}
},
serverPrefetch() {
return this.getPost(); // to do with SSR
},
mounted() {
if (this.Post == null || !this.Post.length) {
this.getPost();
}
},
methods: {
getPost() {
return this.$store.dispatch('loadPost', {PostID: this.$route.params.PostID})
}
}
}
</script>
The problem is that even if I navigate from http://localhost:8080/123-todays-bike-ride to say http://localhost:8080/999-swimming then the URL in the browser address bar changes but the content of the Post view does not change – it remains with the same content as the 123-todays-bike-ride post.
Clearly the watch: { '$route.params.PostID'... bit is not working, but why and how to solve it?
You can try and make it watch deep:
watch: {
"$route.params.PostID": {
handler: function(value) {
console.log(value);
},
deep: true,
immediate: true,
},
},
Also another way of doing this by re-rendering a component without using watch:
by adding :key="$route.params.PostID" to the Post component like:
inside ParentComponent.vue
<template>
<Post :key="$route.params.PostID" />
</template>

Global EventBus to pass data between components does not work

I am trying to use a global eventbus in VueJs but have been unsuccessful so far.
I have the following code. When I navigate from ResetPassword to Login screen, I should see the successMessage with a Your password has been changed successfully. Please login to continue but it always shows a blank.
What could I be doing wrong?
plugins.js:
Vue.prototype.$eventHub = new Vue();
ChangePassword.vue:
methods:
{
ChangePassword()
{
this.$eventHub.$emit('navigation-message', 'Your password has been changed successfully. Please login to continue.');
this.$router.push({ name: 'login'});
},
},
Login.vue:
data() {
return {
successMessage:'',
};
},
created ()
{
this.$eventHub.$once('navigation-message', this.successMessage);
},
beforeDestroy()
{
this.$eventHub.$off('navigation-message');
},
Update: 12/8/2019: I changed the login.vue as per comment by #tony19 but the issue still exists.
Login.vue:
created ()
{
this.$eventHub.$once('navigation-message', (payload)=>
{
updateSuccessMessage(payload);
});
},
methods:
{
updateSuccessMessage(payload)
{
this.successMessage=payload;
},
You need to add this.
created () {
this.$eventHub.$on('navigation-message', payload => {
this.updateSuccessMessage(payload)
})
},
methods: {
updateSuccessMessage(payload) {
this.successMessage = payload
}
}
Also make sure you're actually importing plugin.js globally (e.g. inside your main file where you import Vue) and make sure your components have access to it.
Try this:
created() {
console.log(this.$eventHub)
}