Running setInterval on Vue method - javascript

document.addEventListener("DOMContentLoaded", function(event) {
var app = new Vue({
el: '#app',
data: {
posts: {}
},
mounted: function() {
},
methods: {
updatePosts: function () {
$.get('/api/v1/posts',function(response){
this.posts = response.data;
setInterval(this.updatePosts, 10000);
}.bind(this));
};
},
created: function () {
this.updatePosts();
}
});
});
I'm making an api call and want to run the updatepost method every 10 seconds. Currently, it runs except the 10 second timer gets reset on every page reload. How would I run this function every 10 seconds but not when the page gets refreshed?

I'm not sure if I understand your problem correctly, you want to stop the updatePosts call if the page refreshes, maybe you could use a route param to allow the created event to trigger updatePosts only if said param exists.

Related

Calling function shortly after page load, once results are received from controller

I'm trying to call a computed property (which relies on a data variable to be set from incoming json) upon page creation but it says that it can't read the data for 'undefined'. This is due to the data I need not being fully loaded, I'm pretty sure. When I set it to run 2 seconds after created(), it works just fine.
How can I neatly set this to only run the function on my data variable one time but ONLY once the data results are actually set?
<div id="app">
<div v-for="(value, employee) in employeeFunction" :key="employee">
#{{value}}
</div>
</div>
<script>
var vm =
new Vue({
el: "#app",
data: {
results: [
{//data is in here
}
],
},
created: function(){
this.interval = setInterval(() => this.employeeFunction(), 2000);
},
computed: {
employeeFunction() {
console.log('employee data')
employeeResults = this.results
console.log(employeeResults)
return employeeResults
},
}
});
</script>
Instead of using the created() lifecycle-hook try with mounted()

How to use debounce on `keyup` with Vue.js

I am trying to catch the user started typing, and stopped typing using the debounce function. I tried Lodash and Underscore.js.
On my textArea
v-on:keyup="handler($event)"
handler: function(e) {
this.e = e
if(this.canPublish) {
this.setCanNotPublish()
this.doStuff()
}
var debounceFunction = _.debounce(this.doneTyping(), 5000)
debounceFunction(e)
},
I am getting really frustrated about this. In pure JavaScript I made the test work. But with Vue.js where it uses v-on events, data, methods ...etc., I am not able to make it work.
Method doneTyping
doneTyping: function () {
console.log('done typing....')
}
}
Method doStuff
doStuff: function () {
console.log('started typing....')
}
The intended behaviour is: first the user started typing in the textArea, and it starts the doStuff. And if the user keeps typing in a period shorter than 5 seconds, it will not trigger doStuff again because canPublish is a boolean. Next the user stops typing and then the debounce func is done, and doneTyping fires.
I would do with this two debounced functions, one for started typing which triggers on the leading edge, and one for stopped typing which triggers on the trailing edge.
new Vue({
el: '#app',
created() {
this.startedTyping = _.debounce(this.startedTyping, 5000, {
leading: true,
trailing: false,
})
this.stoppedTyping = _.debounce(this.stoppedTyping, 5000, {
leading: false,
trailing: true,
})
},
methods: {
handleKeydown() {
// This triggers on the leading edge
this.startedTyping()
// This triggers on the trailing edge (after 5s)
this.stoppedTyping()
},
startedTyping() {
console.log('started typing')
},
stoppedTyping() {
console.log('stopped typing')
},
},
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.19/lodash.min.js"></script>
<div id="app">
<textarea #keydown="handleKeydown"></textarea>
</div>
Your code is wrong because you are creating a new debounced function every time the handler is called. You need to have only one debounced function instance that you call each time. It's best to create the debounced function in the created hook.
I often see code like this:
methods: {
myDebouncedFunc: _.debounce(function () {
// Do stuff
}, 1000)
}
This is technically not wrong, but you may not realize that the debounced function will be shared across all instances of that component, which may not be what you want. It's usually best to create the debounced function in the created hook so that each instance of the component gets its own independent debouncing tracking.
Here's how to debounce your method.
doneTyping: _.debounce(function (e) {
console.log('done typing....')
}, 5000)
Then you use it like
handler: function(e) {
this.e = e
if(this.canPublish){
this.setCanNotPublish()
this.doStuff()
}
this.doneTyping() // function is debounced
},

Getting data from a watched variable

I have a beginner question. Maybe I´m just too stupid.
Situation:
I have a interface where I can set alarm timer values via a slider. Everytime the value gets updated, it is written down to a file.
But when I set an interval I dont have access from the callback function to the watched variable, see timeCallback().
Vue.component('alarm-comp', {
data: function() {
return {
data: {
wakeup: {
text: "Get up",
time: 30, //timeout
},
...
},
test: "test",
...
},
watch: {
data: {
handler(val) {
this.saveSettings();
},
deep: true
}
},
mounted: function() {
this.readSettings();
setInterval(() => {this.timerCallback()}, (this.data.wakeup.time) * 1000); // -> time correctly set
},
methods: {
timerCallback() {
console.log(this.test); // -> test
console.log(this.data.wakeup.time); // -> undefined
},
}
Hi mago and welcome to SO.
In VueJS information is sent down to components with props and sent up to the parent with emit event. If you want the parent component to know when the interval is done, you should emit that event up.
Check out this example: https://codepen.io/bergur/pen/jjwZxO?editors=1010
In my alarm component the main thing is
mounted() {
setInterval(() => {
this.$emit('finished', this.wakeup.text)
}, (this.wakeup.time) * 1000
);
},
Here I create the finished event that sends the wakeup text (note that I removed the extra data wrapper)
In my parent object I listen to that event
<Alarm #finished="logMessage" />
And all that logMessage does is this:
methods: {
logMessage(msg) {
console.log('the alarm has finished and sent this message: ', msg)
}
},
Note that setInterval emits the event multiple times.
i'm trying to figure it out since yesterday, for some reason, your code is not executing the mounted hook, i just duplicate your code (is missing a close bracket before watch, maybe just for the example code) and realise that if you change the mounted for other hook like created, this i'll trigger and i'll work, at least in my example.
created() {
this.readSettings();
setInterval(() => {this.timerCallback()}, (this.data.wakeup.time) * 1000);
}
Do you really need the mounted hook, or can you change to created?

Show / hide preloader on page load in Framework7

I want to show a preloader over all the contents when a page is loading and hide it when the page load is finished and show the content (I'm not talking about internal links- like when you type an address in the browser and waiting for the page to load.)
Like this demo: https://demo.app-framework.com/
I’ve tried this:
var app = new Framework7({
// App root element
root: '#app',
// App Name
name: 'My App',
// App id
id: 'com.myapp.test',
on: {
init: function () {
console.log('App initialized');
},
pageInit: function () {
console.log('Page initialized');
app.preloader.hide();
},
}
// ... other parameters
});
var mainView = app.views.create('.view-main');
app.preloader.show();
But it doesn't work it shows the loader like other elements and doesn't hide it, I'm not sure if its something possible. I would appreciate if someone can point me in the right direction.
That's because in the pageInit event you are referring to a variable which is not initialised by the time you are calling (var app), please find the code snippet usefull.
var app = new Framework7({
// App root element
root: '#app',
// App Name
name: 'My App',
// App id
id: 'com.myapp.test',
on: {
init: function () {
console.log('App initialized');
},
pageInit: function () {
console.log('Page initialized');
//app.preloader.hide(); //app is not yet initialized this will return an undefined error.
},
}
// ... other parameters
});
var mainView = app.views.create('.view-main');
app.preloader.show(); //var app is initialized by now
app.on('pageInit', function (page) {
console.log('Page is now initialized');
app.preloader.hide();
});
The docs on Page has a section on Page Events. https://framework7.io/docs/page.html#page-name
Use app.preloader.show(); on an early event, and use app.preloader.hide(); when you want it removed.
pageBeforeIn: function (e, page) {
app.preloader.show();
},
pageAfterIn: function (e, page) {
app.preloader.hide();
},

How to set a timer with a Vue.js class

im just using Vue.js to updates posts on a site im messing around with, this is what ive got so far (im still learning javascript, and not too great at it)
[app.js]
var Vue = require('vue');
Vue.use(require('vue-resource'));
var app = new Vue({
el: '#app',
components: {
'postlist' : require('./components/postlist/postlist.js')
}
});
[postlist.js]
module.exports = {
template: require('./postlist.template.html'),
data: function () {
return {
'search': '',
'posts' : {}
}
},
methods: {
'updatePosts' : function()
{
this.$http.get('api/posts', function(responce, status, request)
{
this.$set('posts', responce.data);
});
}
}
};
What I'm looking for is to have updatePosts fire off every x seconds, how do I do this?
ive tried doing this in the app.js
setInterval(function()
{
app.components.postlist.methods.updatePosts(); // doesnt work
app.postlist.updatePosts(); //doesnt work either
}, 500);
and tried putting the setInterval into the component itself
im pretty lost with this, whats the best way to achieve this?
updatePosts running every x seconds?
I have also trouble with scopes in Vue.
this should work
module.exports = {
template: require('./postlist.template.html'),
data: function () {
return {
'search': '',
posts: {}
}
},
methods: {
updatePosts: function () {
var self = this;
self.$http.get('api/posts', function(responce, status, request) {
self.posts = responce.data;
setTimeout(function(){ self.updatePosts() }, 2000);
});
}
},
created: function () {
this.updatePosts();
}
}
Functions in Vue works kinda different way, because your method updatePosts is not regular function. It is function defined in $vm.methods object. so It can't be called regularly like setTimeout($vm.updatePosts). Actually $vm.updatePosts doesn't exists. if you called it like $vm.updatePosts() it is different story. $vm instance automatically calls its method... So correct way is setTimeout(function(){ self.updatePosts() },2000)
You could start the request cycle in created or somewhere else in the lifecycle. It's also probably better to use recursion here so you can wait for the response to come back before you send off another one. I didn't test this code fully but it should work.
module.exports = {
template: require('./postlist.template.html'),
data: function () {
return {
'search': '',
posts: {}
}
},
methods: {
updatePosts: function () {
this.$http.get('api/posts', function(responce, status, request) {
this.posts = responce.data;
setTimeout(this.updatePosts, 2000);
});
}
},
created: function () {
this.updatePosts();
}
}

Categories

Resources