CodeSpud

How To Make A Timer/Stopwatch Using AngularJS

September 28, 2014

frontendangularjsuijavascript

I’ve got some leeway pushing Khrunus off the ground.  I’ve always been successful using JavaScript’s timing functions but since Khrunus would primarily be built-in in AngularJS. I have to research a way to reuse my timing snippets into proper Angular code.  To study, I built a simple angular app:

Problem

How to use AngularJS to make a time-related app, in this case, a timer for logging elapsed time?

What I need

Before I started this little venture, I need to detail the parameters of the experiment.

Firstly,  I need to layout my application into two sections. The top section will show a digital clock face and a button to toggle(start or stop) the clock. The bottom section will be a table showing start and end times, as well as the total duration. To know that the application is successful, start and end times should be logged. Using those values I can compute for the duration.

We have two modes; an idle state,”stopped” and an active mode,”started”. We need to consider that when coding the helper functions.

Solution

Firstly, we start with a basic AngularJS template. Please note I am assuming you have at least some experience working with HTML, Javascript, and AngularJS.

I need two sections so I make two main DIVs.

Next, in DIV 1,  we add another div to serve as the container for the timer digits and a button.

Next in DIV #2, we format a table with a header and three columns; “Start”, “End” and “Duration(secs)” correspondingly.

What we have now is not very pretty, we’re going to fix that in a bit. Create a CSS file, call it “app.css”. Let’s style everything as follows,

Looking good! 🙂  Now to add the functionality we need. Let’s start with some data binding and a basic controller.

HTML

Javascript

Awesome! For the button, we’re going to use that as a trigger to toggle between modes as well as an indicator to show the user what’s happening.

Now, we can switch between modes, using the button data {{mode}} as a toggle flag. Now to the meat of the application, as a reference I’m going to use this basic clock code I use when I need digital clock displays.

The hero of this application is AngularJS’s $timeout service. The $timeout service gives the user a wrapper for window.setTimeOut. So it still acts like setTimeOut but with the code organization and excellent exception handling that AngularJS provides. Our code should follow this format

We build the clock functionality via a $timeout statement, but first let’s refactor our controller and add two functions to handle the Start and Stop modes.

Now for the $timeout service,

You can see that we used the timeout service to recursively call the StartTimer function. When you call $timeout, just as window.setTimeOut, you create a timing object that we then save to our variable ‘tmPromise’. We’ll get into more of that later just take a note of it. Since we’re really making a stopwatch and not a clock that tells the current time, let’s recode. We need the current time so we use date.getTime(). Adding two more variables timeStart and timeEnd. When we button is clicked, we save the time to timerStart. Every time the timeout completes and we call StartTimer, the value of $scope.timeEnd changes. We then subtract $scope.timeStart to get the current elapsed time in milliseconds. We add some normalization code and we end up with this,

Now for the stopTimer function, issuing the cancel method will stop the $timeout service. Remember the variable we made earlier, ‘tmPromise’. We will use that as the parameter for our cancel call illustrated below. We then collect the start and end times and push that into the history array.

Conclusion

Yay, we just made an AngularJS timer widget. Adding a service to insert a line in our table we end up with this.

This is a very simple implementation. One that did not need a unit test but if we wanted to, we can use a $timeout.flush() method. More details from the reference links below.

See the app in action here

** UPDATE: Code sample here here

Download all the source here.

References

By @codespud  
DISCLAIMER This is my personal weblog and learning tool. The content within it is exactly that – personal. The views and opinions expressed on the posts and the comments I make on this Blog represent my own and not those of people, institutions or organisations I am affiliated with unless stated explicitly. My Blog is not affiliated with, neither does it represent the views, position or attitudes of my employer, their clients, or any of their affiliated companies.