angularcountdown

Countdown timer in Angular17


I'm trying to make a countdown timer in my home component. It kind of looks like this.

The countdown

Here is the place I put countdown in html file:

<div>
  {{displayTime}}
</div>

My Home.ts file:

ngOnInit(): void {
  this.countdownSubscription = interval(1000).subscribe(val => this.displayTime = this.countdownTimer(val))
}

countdownTimer(seconds: number) {
   const totalSeconds = Math.floor((this.targetDay - Date.now()) / 1000);
   const days = Math.floor(totalSeconds / (60 * 60 * 24));
   const hours = Math.floor((totalSeconds % (60 * 60 * 24)) / (60 * 60));
   const minutes = Math.floor((totalSeconds % (60 * 60)) / 60);
   const remainingSeconds = totalSeconds % 60;
   const formattedDays = days < 10 ? '0' + days : days;
   const formattedHours = hours < 10 ? '0' + hours : hours;
   const formattedMinutes = minutes < 10 ? '0' + minutes : minutes;
   const formattedSeconds = remainingSeconds < 10 ? '0' + remainingSeconds : remainingSeconds;
   return formattedDays+":"+formattedHours+":"+formattedMinutes+":"+formattedSeconds
}

ngOnDestroy(): void {
   this.countdownSubscription.unsubscribe();
}

When I log it on console, it works fine:

enter image description here

But on my localhost:4200, it not loading and always spin around:

enter image description here

Even in the console or terminal, nothing like errors show up:

enter image description here

Can anyone help me with this problem, thank you a lot!!!


Solution

  • you forget severals things:

     this.countdownSubscription = interval(1000).subscribe(val =>
             //here you give value to the variable "displayTime"
             this.displayTime=this.countdownTimer(val)
     );
    
    countdownTimer(seconds: number) {
       ...
       //you need return something
       return formattedDays+":"+formattedHours+":"+formattedMinutes+":"+formattedSeconds
    }
    

    BTW, you can use pipe async to makes Angular unsubscribe automatically

      countdownObs$!:Observable<string> //declare an observable
    
    ngOnInit()
    {
       //see that you **not** subscribe, simply transform the observable
       //using map
       this.countdownObs$= interval(1000).pipe(
           map(val =>this.countdownTimer(val))
        )
    }
    

    And you use

    {{countdownObs$|async}}
    

    pipe async mannage the unsubscription (don't forget import AsyncPipe or CommonModule in your component/Module)

    A stackblitz with both approach