clear interval on another function vue js - javascript

I'm confused how to add a set Interval variable in my vue file myTimer = setInterval(function, time).
The goal of my program is to change the number variable every 3 seconds, to access the object that I created to let it display different background images but I also have 2 buttons that can navigate through the background as well.
This is my template code
<div class="background" :style="{backgroundImage: `url(${Images[`${number}`].picture})`}">
<div class="content_container">
<div v-on:click="prev" class="prevButton"><p><</p></div>
<div class="title_container">
<div class="theTitle"><p>{{Images[`${number}`].Title}}</p></div>
</div>
<div v-on:click="next" class="nextButton"><p>></p></div>
</div>
</div>
This is my set Interval code
export default {
data: () => ({
number: 0,
myTimer
}),
mounted:function() {
this.$nextTick(() => {
this.timer();
});
},
methods:{
timer: function() {
var myTimer = setInterval(this.counter, 3000);
},
counter:function(){
if(this.number >= (this.Images.length -1)){
this.number = 0;
}
else{
this.number +=1;
}
},
next()
{
clearInterval(this.myTimer)
if(this.number >= (this.Images.length -1)){
this.number = 0;
}
else{
this.number +=1;
}
},
I want to clearInterval at the next() function how can I access the variable from another function.

your myTimer need be in this context.
export default {
data: () => ({
number: 0,
myTimer: 0, // init myTimer
}),
mounted: function () {
this.$nextTick(() => {
this.timer();
});
},
methods: {
timer: function () {
this.myTimer = setInterval(this.counter, 3000); // in this.myTimer
},
counter: function () {
if (this.number >= this.Images.length - 1) {
this.number = 0;
} else {
this.number += 1;
}
},
next() {
clearInterval(this.myTimer); // clear
if (this.number >= this.Images.length - 1) {
this.number = 0;
} else {
this.number += 1;
}
this.timer(); // start next
},
},
};

Related

Having value loop from 100 to 0 - Vuejs

I'm trying to have my power value go from 100 to 0 and back from 0 to 100. This will be for a power meter where the user will hit a button to stop it at a random value.
Just need help getting the loop working properly
export default {
data() {
return {
power: 100,
};
},
}
watch:{
power: {
handler(value) {
if (value == 100 || value > 0) {
setTimeout(() => {
this.power--;
}, 100);
} if (value == 0) {
setTimeout(() => {
this.power++;
}, 100);
}
},
immediate: true
},
}
Maybe you could find other solutions also, but this is what comes in my mind:
<template>
<section v-if="!showPart">
<!-- This part is shown when program is cycling looping numbers -->
<div v-if="power1">
{{power}}
</div>
<div v-else>
{{powerReverse}}
</div>
</section>
<div v-else>
<!-- This part is shown when user clicks to select a number -->
{{showValue}}
</div>
<button #click="stopFunc">{{textBtn}}</button>
</template>
<script>
export default {
name: "powerCompo",
data() {
return {
speed: 100, // speed of loop
power: 99, // start point of loop
power1: true, // for change view in increase and decrease states
powerReverse: 0, // for increasing loop after reach to "0"
showValue: "nothing selected", // showing the selected value
decrease: null, // for clearing "timeout" in decrease mode
increase: null, // for clearing "timeout" in increase mode
showPart: false, // for changing view between "loop" or "stop" modes
textBtn: "click for stop" // defines the text of btn
};
},
watch:{
power: {
handler(value) {
this.decrease = setTimeout(() => {
this.power--;
}, this.speed);
if (this.power === 0) {
clearTimeout(this.decrease);
console.log("decrease");
this.power1 = false;
this.powerReverse = 0;
this.powerReverse++;
}
},
immediate: true
},
powerReverse(newValue) {
this.increase = setTimeout(() => {
this.powerReverse++;
}, this.speed);
if (this.powerReverse === 100) {
clearTimeout(this.increase);
console.log("increase");
this.power1 = true;
this.power = 100;
this.power--;
}
}
},
methods: {
stopFunc: function ($event) {
/* This function is called each time the user clicks on button. Then if the text of button is "click for cycling again", it calls "resetFunc()" method and if not, it stops looping and shows the selected value. */
if ($event.target.innerText === "click for cycling again") {
this.resetFunc();
} else {
if (this.power1) {
this.showValue = this.power;
if (this.showValue === 100) {
this.showValue = 99;
this.power = 99;
}
} else {
this.showValue = this.powerReverse;
}
this.showPart = true;
clearTimeout(this.increase);
clearTimeout(this.decrease);
this.textBtn = "click for cycling again"
}
},
resetFunc: function () {
clearTimeout(this.increase);
clearTimeout(this.decrease);
this.textBtn = "click for stop"
this.showPart = false;
this.power= 100;
this.power1= true;
}
}
}
</script>
With the above component you can loop between [1, 99] inclusive.

How to stop a timer upon keydown?

I have a text input box, which updates the 'ticket' with my the input when the timer finishes, instead of every keystroke which was the previous behaviour. However this causes a reload of the text input often while I am still using it.
I believe the best solution would be for the timer to reset every keydown event, but the few solutions I've tried haven't worked well, so I'd like to see if that's what is the most straightforward route to taker in my situation.
Relevant Code Below
strValue: {
get: function () {
return this.attachment.strValue;
},
set: function (val) {
let self = this; setTimeout(function(){ return self.updateAttachment([self.attachment.id, { strValue: val }]) },8000) },
},
Full section of code:
computed: {
...mapGetters(['allDocumentTypeGroups', 'currentTicketCaseFiles', 'activeAttachmentIndex', 'showAttachmentsPreview', 'activeAttachments']),
attachmentAcceptedLabel() {
return this.attachmentAccepted ? this.t('accepted') : this.t('ignored');
},
attachmentAccepted: {
get: function () {
return !this.attachment.ignoreAttachment;
},
set: function (val) {
return this.updateAttachment([this.attachment.id, { ignoreAttachment: !val }]);
},
},
documentType: {
get: function() {
return this.attachment.documentTypeId;
},
set: function(val) {
return this.updateAttachment([this.attachment.id, { documentTypeId: val }]);
},
},
approveAttachment: {
get: function() {
return this.attachment.approvedAttachment;
},
set: function(val) {
return this.updateAttachment([this.attachment.id, { approvedAttachment: val }]);
},
},
strValue: {
get: function () {
return this.attachment.strValue;
},
set: function (val) {
let timer;
if(timer){
clearTimeout(timer);
}
let self = this;
timer = setTimeout(function(){ return self.updateAttachment([self.attachment.id, { strValue: val }]) },8000) },
},
},
You can use clearTimeout(timer) as shown below:
let timer;
strValue: {
get: function () {
return this.attachment.strValue;
},
set: function (val) {
if(timer){
clearTimeout(timer);
}
let self = this;
timer = setTimeout(function(){ return self.updateAttachment([self.attachment.id, { strValue: val }]) },8000) },
},
},
This is a very simple implementation of a throttled input. Please let me know if I'm missing something.
const input = document.getElementById('input');
const ticket = document.getElementById('ticket');
const threshold = 2000;
let timeout = null;
const onKeydownHandler = () => {
// CLEAR PREVIOUS TIMEOUT WHEN A KEY IS PRESSED.
clearTimeout(timeout);
// "RESTART" THE TIMEOUT.
timeout = setTimeout(() => {
// UPDATE YOUR VALUE HERE.
ticket.innerText = `Ticket Value: ${input.value}`;
}, threshold);
};
input.addEventListener('keydown', onKeydownHandler);
// REMOVE THIS
(() => {
const counter = document.getElementById('counter');
let interval = null;
let count = threshold;
input.addEventListener('keydown', () => {
clearInterval(interval);
count = threshold;
interval = setInterval(() => {
count -= 50;
counter.innerText = `Time Left: ${count}ms`;
if (count <= 0) {
clearInterval(interval);
}
}, 50);
});
counter.innerText = `Time Left: ${count}ms`;
})();
// REMOVE THIS
div {
margin: 20px;
}
<input id='input' type='text' placeholder='Start writing...'></input>
<div>
<span id='ticket'>Ticket Value:</span>
</div>
<!--REMOVE THIS-->
<div>
<span id='counter'></span>
</div>
<!--REMOVE THIS-->

clearInterval if pagination page is bigger than 1

i'm working on small project using Vue.js i have created a pagination system to display my database users in a table, i have a small issue, i would like to know how can i stop the setinterval if my getResult function page variable is bigger than 1.
this is my code :
data(){
return {
editMode : true,
customer_id : null,
laravelData : {},
formFields : {}
}
},
methods:{
getResults(page = 1){
axios.get('Thirdparty/loadCustomers/' + page).then(response => {
this.laravelData = response.data;
});
}
},
created(){
self = this;
setInterval(function(){
self.getResults();
}, 5000);
}
First and foremost, always capture identifiers from setInterval and setTimeout.
By capturing your interval ID you can later remove it from within your callback when the page value is larger than its default (1).
EDIT: The OP would like to be able to reset the interval when page resets.
created() {
this.resetInterval();
},
methods: {
resetInterval() {
this.currentInterval && clearInterval(this.currentInterval);
this.currentInterval = setInterval(() => this.getResults(), 5000);
},
getResults(page = 1) {
if (page == 1 && !this.currentInterval) {
this.resetInterval();
} else {
clearInterval(this.currentInterval);
}
axios.get('Thirdparty/loadCustomers/' + page).then(response => {
this.laravelData = response.data;
});
}
}
data(){
return {
editMode : true,
customer_id : null,
laravelData : {},
formFields : {},
currentInterval : null
}
},
methods:{
getResults(page = 1){
clearInterval(this.currentInterval);
axios.get('Thirdparty/loadCustomers/' + page).then(response => {
this.laravelData = response.data;
});
},
created(){
self = this;
self.currentInterval = setInterval(function(){
self.getResults();
}, 5000);
}

Vue js method with argument and setTimeout

I can't figure out why this code works..
data: {
return {
userMinerals: 0,
mineralsLimit: 1000,
miners: 0,
superMiner: 0,
minerPrice: 10,
superMinerPrice: 100,
minersLimit: 10
}
}
methods: {
counter() {
setInterval(() => {
this.userMinerals += this.miners;
if(this.checkLimit(this.userMinerals, this.mineralsLimit)) {
this.userMinerals = this.mineralsLimit;
}
}, 100);
},
addMiner() {
if (this.userMinerals >= this.minerPrice) {
this.miners += 1;
this.userMinerals -= this.minerPrice;
this.counter();
}
}
}
.. but if I try to put parameters into counter() the code stops working
methods: {
counter(typeOfCredits) {
setInterval(() => {
typeOfCredits += this.miners;
if(this.checkLimit(this.userMinerals, this.mineralsLimit)) {
typeOfCredits = this.mineralsLimit;
}
}, 100);
},
addMiner() {
if (this.userMinerals >= this.minerPrice) {
this.miners += 1;
this.userMinerals -= this.minerPrice;
this.counter(this.userMinerals);
}
}
}
From the console I can see that typeOfCredits gets incremented as it should but it doesn't update the value in the view.
Thx for help
You cant reference a parameter and expect it to be changed outside, but you can pass a reference to an object that can change something outside.
var $this = this;
this.counter({
get() { return $this.userMinerals },
set(val) { $this.userMinerals = val }
});
and then use in the counter like this
counter(typeOfCredits) {
setInterval(() => {
typeOfCredits.set(typeOfCredits.get() + this.miners);
if(this.checkLimit(this.userMinerals, this.mineralsLimit)) {
typeOfCredits.set(this.mineralsLimit);
}
}, 100);
},
jsfiddle
typeOfCredits is a parameter to the function. Parameters are passed by value. Modifying it is like modifying a local variable.

In Vue.js, is this a wrong writing for v-on?

i want to make two button to input number.
but when the left one goes to 10, it looks like this:
enter image description here
i want it to be 2 on the left while 0 on the right side.
so i changed my code:
<div id="counter-event-example">
<p>{{ total }}</p>
<button-counter v-on:increment="incrementTotal2"></button-counter>
<button-counter v-on:increment2="incrementTotal"></button-counter>
</div>
Vue.component('button-counter', {
template: '<button v-on:click="increment">{{ counter }}</button><button v-on:click="increment2">{{ counter }}</button>',
data: function () {
return {
counter: 0
}
},
methods: {
increment: function () {
this.counter += 1
this.$emit('increment')
},
increment2:function () {
if(this.counter === 10){
this.counter = 0;
this.increment();
}
this.$emit('increment2')
}
},
})
new Vue({
el: '#counter-event-example',
data: {
total: 0
},
methods: {
incrementTotal: function () {
this.total += 1
},
incrementTotal2: function () {
this.total = this.total +10
}
}
})
but it did'nt work..enter image description here
i click the right button, the total number wont change.
You render 2 components each of them should render 2 buttons. Sounds about right? If you check Element Inspector you will see that rendered only 2 buttons. 2 + 2 === 2 - something is fishy...
Dev version of Vue telling you in console "Error compiling template... Component template should contain exactly one root element".
So each button-counter render first button => writing you warning => and ignoring second button.
<div id="counter-event-example">
<p>{{ total }}</p>
<button-counter-1 #increment="incrementTotal"></button-counter-1>
<button-counter-2 #increment="incrementTotal"></button-counter-2>
</div>
Vue.component('button-counter-1', {
template: '<button #click="increment1">{{ counter }}</button>',
data: function() {
return { counter: 0 }
},
methods: {
increment1: function () {
this.counter++;
this.$emit('increment', 10);
}
}
});
Vue.component('button-counter-2', {
template: '<button #click="increment2">{{ counter }}</button>',
data: function() {
return { counter: 0 }
},
methods: {
increment2: function () {
this.counter++;
this.$emit('increment', 1);
}
}
})
new Vue({
el: '#counter-event-example',
data: {
total: 0
},
methods: {
incrementTotal: function (n) {
this.total += n;
},
}
})

Categories