Angular Countdown Timer

Angular countdown timer showing days, hours, minutes, and seconds.

I created this Angular countdown timer because it’s often difficult to find exactly what I need. Whether it’s an Angular or React component. A specific service. Or an Axios GET request with error handling that doesn’t cause 500 errors by default.

Git Repo

Regardless, I’m often amazed how much developers can accomplish in such few lines of code. No frameworks or libraries, just code in a native language. I think this is one of those times. Here’s a neat component—done so with minimal code.

  • Begin by setting the variables.
  • Basic date reference followed by the current time.
  • targetDate is of course the desired date to countdown from.
  • targetTime is the numeric version of the date.
  • difference is then subtracted by now (numerically).
  • The months array is used to illustrate the month name in the template. Feel free to substitute this w/ template literals.
  • We’re using basic ViewChild to retrieve the DOM elements, which are then populated w/ values. Some may argue Angular’s Renderer2 would be a better approach due to potential injection sinks. So this may change in a future version.
  • ngAfterViewInit is used because ViewChild elements do not become available at early life cycle hooks.
  • The isNaN bit is pertinent because days is not a number before it’s calculated. So unless you want NaN showing in the UI, use the ternary at the end of the ngAfterViewInit hook block.
  • In this hook, we call a repeating fn every 1 second. It updates the difference between then and now and divides it by an equation to make it readable/ presentable.
  • tickTock() creates a new date, and updates the aforementioned values. That’s it!

Angular Countdown Timer Typescript

If you’re familiar with Angular this shouldn’t be foreign to you. If it is though, feel free to leave a comment. Always happy to explain code. Regardless, understand the code. It’s not so much about the syntax but more-so about the concept. Building and applying conceptually makes us better developers. In turn, it becomes easier to learn new languages because we apply concepts. Then simply piece them together.

date: any;
now: any;
targetDate: any = new Date(2022, 12, 1);
targetTime: any = this.targetDate.getTime();
difference: number;
months: Array<string> = ["January", "February", "March", "April",
"May", "June", "July", "August", "September", "October", "November", "December"];

// Template literals is ideal for this scenario
currentTime: any = this.months[this.targetDate.getMonth()] +
' ' + this.targetDate.getDate() + ', ' + this.targetDate.getFullYear();

@ViewChild("days", { static: true }) days: ElementRef;
@ViewChild("hours", { static: true }) hours: ElementRef;
@ViewChild("minutes", { static: true }) minutes: ElementRef;
@ViewChild("seconds", { static: true }) seconds: ElementRef;

ngAfterViewInit() {
  setInterval(() => {
    this.tickTock();
    this.difference = this.targetTime - this.now;
    this.difference = this.difference / (1000 * 60 * 60 * 24);
    !isNaN(this.days.nativeElement.innerText)
      ? (this.days.nativeElement.innerText = Math.floor(this.difference))
      : (this.days.nativeElement.innerHTML = "<img src='https://i.gifer.com/VAyR.gif' />");
    }, 1000);
}

tickTock() {
  this.date = new Date();
  this.now = this.date.getTime();
  this.days.nativeElement.innerText = Math.floor(this.difference);
  this.hours.nativeElement.innerText = 23 - this.date.getHours();
  this.minutes.nativeElement.innerText = 60 - this.date.getMinutes();
  this.seconds.nativeElement.innerText = 60 - this.date.getSeconds();
}
<div class="count-down-timer">
  <p>Countdown to {{currentTime}}</p>
  <div class="wrapper">
    <div class="description">
      <p>Days</p>
      <p>Hours</p>
      <p>Minutes</p>
      <p>Seconds</p>
    </div>
    <div class="times">
      <p #days></p>
      <p #hours></p>
      <p #minutes></p>
      <p #seconds></p>
    </div>
  </div>
</div>
.count-down-timer {
  box-shadow: 2px 6px 9px 2px rgb(0 0 0 / 20%);
  text-align: center;
  background-color: black;
  color: white;
  border-radius: 6px;
  padding: 10px;
    > p { margin: 5px 0 15px 0; }

  .wrapper {
    .description, .times {
      display: grid;
      grid-template-columns: repeat(4, calc(25% - 8px));
      grid-column-gap: 10px;
    }

    .description {
      > p { font: normal 14px sans-serif; }
    }

    .times {
      p {
        letter-spacing: -5px;
        font: normal 50px courier, sans-serif;
      }
    }
  }
}

Hope you enjoyed this post. Regardless, I’d be very grateful if you left a comment below telling me what you did or didn’t like. If you get stuck, see the Stackblitz link here. Otherwise, feel free to use this wherever you’d like. Advertisements, a test, games, etc. Additionally, if you think this Angular countdown timer can be improved, let me know!

2 Comments

Leave a Reply

Your email address will not be published.


*