0

I have created a LWC countdown timer but timer does not decrease in real-time.

enter image description here

I have looked through similar posts regarding SetInterval and try to implement the recommandations

Arrow function not working for setInterval

LWC JS counter variable using setInterval

But still, I can't get my compoment showing timer running in real time. I believe it is because the SetInterval function is nested inside my wire function. Because when I tried to create a sample timer as shown in the 1st link, it works but as soon I put it inside the wire function. The counter stops working.

here is my component html:

<template>
    <lightning-card title="Timer" icon-name="standard:account">
        <p class="deadline">   Deadline: {timer}</p>
    </lightning-card>
</template>

js:

import { LightningElement, api, track, wire } from 'lwc';
import { getRecord } from 'lightning/uiRecordApi';
import DEADLINE_FIELD from'@salesforce/schema/Milestone__c.Deadline__c';

export default class LwcMilestoneCountdownTimer extends LightningElement {
    @api recordId;
    data;
    error;
    milestone;
    deadline;
    timer;
    setTimeInterval;
   
    @wire(getRecord, {recordId: '$recordId', fields:[DEADLINE_FIELD]})
    wireMilestone({ data, error }) {
        if(data) {
            this.milestone = data;
           
            this.deadline = this.milestone.fields.Deadline__c.value;
            let day = new Date(this.deadline);
           
            let ddate = day.getTime();
            console.log('>>>ddate getTime() ' +ddate) //getTime() output date in this format "1653955200000"

            let currentDateTime = new Date().getTime();
            console.log( 'currentDateTime getTime ' + currentDateTime );
            
            let distance = ddate - currentDateTime;
            console.log( 'diff deadlineDate - now ' + distance ); 

            this.setTimeInterval = setInterval(() => {
                    // If the count down is finished, reset to Zero
                    if (distance < 0) {
                        clearInterval(setTimeInterval);
                    } else {
                        let days = Math.floor(distance / (1000 * 60 * 60 * 24));
                        let hours = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
                        let minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60));
                        let seconds = Math.floor((distance % (1000 * 60)) / 1000);

                        this.timer = days + "d " + hours + "h " + minutes + "m " + seconds + "s "; 
                    }
                            
            }, 1000);

        } else if(error) {
            this.error = error;
            console.log(  'Error: ' + JSON.stringify(error) );
            this.ddate = undefined;
        }
       
    } 
}

1 Answer 1

0
    // If the count down is finished, reset to Zero
    let day = new Date(this.deadline);

    let ddate = day.getTime();
    console.log(">>>ddate getTime() " + ddate); //getTime() output date in this format "1653955200000"

    let currentDateTime = new Date().getTime();
    console.log("currentDateTime getTime " + currentDateTime);

    let distance = ddate - currentDateTime;
    console.log("diff deadlineDate - now " + distance);

All of this is only called when the wire handler is called, so the time doesn't update until the next time the wire method is called. Put the calculations inside the interval function itself.

Also remember to clear the timer before starting a new one, e.g. if the deadline changes. Finally, you forgot this. on clearInterval in your code. Don't forget where your data is stored.

Here's an updated version of your code:

import { LightningElement, api, track, wire } from "lwc";
import { getFieldValue, getRecord } from "lightning/uiRecordApi";
import DEADLINE_FIELD from "@salesforce/schema/Milestone__c.Deadline__c";

export default class LwcMilestoneCountdownTimer extends LightningElement {
  @api recordId;
  data;
  error;
  milestone;
  deadline;
  timer;
  setTimeInterval;

  @wire(getRecord, { recordId: "$recordId", fields: [DEADLINE_FIELD] })
  wireMilestone({ data, error }) {
    if (data) {
      this.milestone = data;

      this.deadline = getFieldValue(data, DEADLINE_FIELD);
      clearInterval(this.setTimeInterval);
      this.setTimeInterval = setInterval(() => {
        // If the count down is finished, reset to Zero
        let day = new Date(this.deadline);

        let ddate = day.getTime();
        console.log(">>>ddate getTime() " + ddate); //getTime() output date in this format "1653955200000"

        let currentDateTime = new Date().getTime();
        console.log("currentDateTime getTime " + currentDateTime);

        let distance = ddate - currentDateTime;
        console.log("diff deadlineDate - now " + distance);
        if (distance < 0) {
          clearInterval(this.setTimeInterval);
        } else {
          let days = Math.floor(distance / (1000 * 60 * 60 * 24));
          let hours = Math.floor(
            (distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)
          );
          let minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60));
          let seconds = Math.floor((distance % (1000 * 60)) / 1000);

          this.timer =
            days + "d " + hours + "h " + minutes + "m " + seconds + "s ";
        }
      }, 1000);
    } else if (error) {
      this.error = error;
      console.log("Error: " + JSON.stringify(error));
      this.ddate = undefined;
    }
  }
}

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .