realtime clock with vue js - vue.js

I've written a small clock component for one of my projects,
but I didn't get the value for my clock refreshed.
A short extract of my code:
time() {
let now = new Date();
let hour = this.zeroPadding(now.getHours());
let minute = this.zeroPadding(now.getMinutes());
let second = this.zeroPadding(now.getSeconds());
console.log(hour.toString() + minute.toString() + second.toString())
if(!this.realtime)
return this.value
else
return hour.toString() + ":" + minute.toString() + ":" + second.toString()
}
},
mounted() {
setInterval(() => {
this.time()
}, 1000)
},
beforeDestroy () {
clearInterval(this.polling)
}
Does anyone finde the mistake?
Did I understand the polling wrong?
Greetings,
Matthias

The time value that you want to display needs to be a data / computed property so that it's reactive and Vue can track it. Concise way to do it:
export default {
data() {
return {
interval: null,
time: null
}
},
beforeDestroy() {
// prevent memory leak
clearInterval(this.interval)
},
created() {
// update the time every second
this.interval = setInterval(() => {
// Concise way to format time according to system locale.
// In my case this returns "3:48:00 am"
this.time = Intl.DateTimeFormat(navigator.language, {
hour: 'numeric',
minute: 'numeric',
second: 'numeric'
}).format()
}, 1000)
}
}

Related

Vue clearInterval cant stop timer (reset timer)

I try to write function to restart setInterval timer:
data() {
return {
intervalId: undefined,
backlightTimerSeconds: 5000,
}
},
I have an method:
timerBacklightOff() {
const interval = 1000
this.intervalId = setInterval(() => {
this.backlightTimerSeconds -= interval
console.log('timerBacklightOff', this.backlightTimerSeconds)
if(this.backlightTimerSeconds <= 0) {
this.setBacklight(false)
this.clearTimerBacklight()
return
}
}, interval)
},
In antoher method I have method to clear interval:
clearTimerBacklight() {
if(!this.intervalId) return
this.backlightTimerSeconds = 0
clearInterval(this.intervalId)
this.intervalId = undefined
this.backlightTimerSeconds = 5000
},
I runned method clearTimerBacklight using button.
I have a problem, blecause when I running method clearTimerBacklight, then not stop setInterval and console.log('timerBacklightOff', this.backlightTimerSeconds) still counter down. How I can restart setInterval to basis time?

Waiting time counter for each object in array Vue js

To get in context, I have a table that shows incoming calls and the waiting time for every call. The data array looks like:
[
{
id: 1,
patient_name: lorem ipsum,
created_at: 2022-02-02 09:10:35,
...
},
{
id: 2,
patient_name: dolor ipsum,
created_at: 2022-02-02 09:00:35,
...
}
]
I'm trying to figure out how to assign a setTimeout for each object, but I'm completely lost.
So far, I found that a counter can be made through a watcher, but of course this only acts as a "global" counter.
watch: {
timerCount: {
handler (value) {
if (value > 0) {
setTimeout(() => {
this.timerCount++
}, 1000)
}
},
immediate: true // This ensures the watcher is triggered upon creation
}
},
Is there a way to use a function to show a counter on each object? I was thinking in something like this:
<template>
<span v-for="call in calls" :key="call.id">
Requested at: {{ call.created_at }}
waiting time: {{ showWaitingTime(call.created_at) }} // <- Not sure if this can be done
</span>
</template>
...
<script>
....
methods: {
showWaitingTime (created_at) {
// get diff in seconds between created_at and now
// do something here with a timeOut() to increment the object property...
}
}
</script>
In addition, I would like to return the waiting time in HH:mm:ss format.
One solution is to wrap the {{ showWaitingTime(call.created_at) }} with a <span> that is keyed on timerCount, so that the <span> is re-rendered when timerCount changes (thus calling showWaitingTime again to compute the new time string):
In the template, wrap the timestamp string with a <span> that has its key bound to timerCount:
waiting time: <span :key="timerCount">{{ showWaitingTime(call.created_at) }}</span>
In a watcher on calls, use setInterval to start a periodic timer. Be sure to stop the timer with clearInterval before starting a new timer and when unmounting the component.
export default {
beforeUnmount() {
clearInterval(this._updateTimer)
},
// Vue 2 equivalent of beforeUnmount()
beforeDestroy() {
clearInterval(this._updateTimer)
},
watch: {
calls: {
handler(calls) {
clearInterval(this._updateTimer)
if (calls.length) {
this._updateTimer = setInterval(() => this.timerCount++, 1000)
}
},
immediate: true,
},
},
}
The watcher you have on timerCount is effectively implementing setInterval. Remove that code since it's obviated by the code in step 2.
export default {
watch: {
// timerCount: {⋯} // ⛔️ remove this watch
}
}
In showWaitingTime(), calculate the HH:mm:ss from the difference between the given time and now:
export default {
methods: {
showWaitingTime(created_at) {
const diff = new Date() - new Date(created_at)
const twoD = x => `${Math.floor(x)}`.padStart(2, '0')
const HH = twoD((diff / (60 * 60 * 1000)) % 24)
const mm = twoD((diff / (60 * 1000)) % 60)
const ss = twoD((diff / 1000) % 60)
return `${HH}:${mm}:${ss}`
},
},
}
demo

Countdown variable (HH:mm:ss)

I parse a date YYYY-mm-dd and calculate the difference till midnight. The result will be always under 24h, for example 10:01:10 - HH:mm:ss till it expires. I wonder how I could achieve a countdown functionality with the given example.
<template>
<Label :text="date.expires | readableTime"></Label>
</template>
filters: {
readableTime(value) {
var now = moment(new Date());
var end = moment(value);
var diff = moment.duration(end.diff(now));
try {
return moment.utc(diff.as("milliseconds")).format("HH:mm:ss");
} catch (e) {
return "00:00:00";
}
}
}
You must use use timer and reactive data property. I recommend you to safe diff to components data, start timer on component mount and clear it beforeDestroy
data() {
return {
diff: this.calculareDiff()
}
}
methods: {
calculareDiff() {
const now = moment(new Date());
const end = moment(this.date.expires);
this.diff = moment.duration(end.diff(now));
}
},
mounted() {
this.timer = setInterval(() => this.calculareDiff(), 1000)
},
beforeDestroy() {
clearInterval(this.timer)
}

Wait until API fully loads before running next function -- async/await -- will this work?

I am a beginner with Javascript with a bit of knowledge of VueJs. I have an array called tickets. I also have a data api returning two different data objects (tickets and user profiles).
The tickets have user ids and the user profiles has the ids with names.
I needed to create a method that looks at both of that data, loops through it, and assigns the full name of the user to the view.
I was having an issue where my tickets object were not finished loading and it was sometimes causing an error like firstname is undefined. So, i thought I'd try and write an async/await approach to wait until the tickets have fully loaded.
Although my code works, it just doesn't "feel right" and I am not sure how reliable it will be once the application gets larger.
Can I get another set of eyes as to confirmation that my current approach is OK? Thanks!
data() {
return {
isBusy: true,
tickets: [],
userProfiles: [],
}
},
created() {
this.getUserProfiles()
this.getTickets()
},
methods: {
getUserProfiles: function() {
ApiService.getUserProfiles().then(response => {
this.userProfiles = response.data
})
},
getTickets() {
ApiService.getTickets().then(response => {
this.tickets = response.data
this.assignNames(this.tickets)
this.isBusy = false
})
},
// lets wait until the issues are loaded before showing names;
async assignNames() {
let tickets = await this.tickets
var i
for (i = 0; i < this.tickets.length; i++) {
if (tickets[i].assigned_to !== null) {
const result = this.userProfiles.filter(profile => {
return profile.uid == tickets[i].assigned_to
})
tickets[i].assigned_to = result[0].firstname + ' ' + result[0].lastname
}
}
}
}
}
</script>
There are several ways you could do this. Here is the one I prefer without async/await:
created() {
this.load();
},
methods: {
getUserProfiles: function() {
return ApiService.getUserProfiles().then(response => {
this.userProfiles = response.data
})
},
getTickets() {
return ApiService.getTickets().then(response => {
this.tickets = response.data
})
},
load() {
Promise.all([
this.getUserProfiles(),
this.getTickets()
]).then(data => {
this.assignNames();
this.isBusy = false;
});
},
assignNames(){
const tickets = this.tickets;
for (let i = 0; i < this.tickets.length; i++) {
if (tickets[i].assigned_to !== null) {
const result = this.userProfiles.filter(profile => {
return profile.uid == tickets[i].assigned_to
})
tickets[i].assigned_to = result[0].firstname + ' ' + result[0].lastname
}
}
}
}

VueJS: setInterval method not working properly

Please tell me what am i doing wrong? I want to active 'cloth' update every 2 sec. Still learning vue. Thanks
data() {
return {
clothes: ['t-shirts', 'sneakers', 'jackets'],
count: 0,
cloth: ''
}
},
methods: {
startInterval() {
setInterval(() => {
this.cloth = this.clothes[this.count]
this.count++
if (this.count >= this.clothes.length) {
this.count = 0;
}
}, 2000)
}
}
Vue has a life cycle that you can leverage to complete this objective. You can hook into the created function and execute your interval within:
created() {
this.startInterval()
},
This is not a method. It will be a sibling to your data and method properties.