Hi,
I want to make a web page and display a count down for example 5 minutes. It will count from 05:00.00 to 00:00.00 in 10ms interval. There will be a start button to start the timer. Timer will be shown on page as format 04:45.23.
After reaching 0, I want to display something (text in div or span).
How is it possible?
Hey @kahlenberg There is a pull request in the queue for a new dcc.Timer
component that will make this super easy to do. You can track the progress and see a preview here:
plotly:dev
← AnnMarieW:timer
opened 01:41PM - 03 May 21 UTC
## dcc.Timer()
The new Timer component is a response to the discussion in [#8… 57](https://github.com/plotly/dash-core-components/issues/857).
`dcc.Timer` is based on the `dcc.Interval` component. It has all the functionality of `dcc.Interval` plus these new features:
- Operate the timer in either `countdown` or `stopwatch` (count up) modes.
- Specify custom messages to display at certain times.
- Automatically convert milliseconds into human readable times. For example, 1337000000ms can be display as:
'15d 11h 23m 20s' See other available formats in the `timer_format` prop.
- Specify certain times to trigger a callback. This makes it easy to start or stop jobs at a specified elapse time.
- Improve load and performance times because updates can happen clientside. This makes it unnecessary to fire a callback
frequently (ie every interval) just to update a countdown/stopwatch message.
#### Component Properties
|Prop name|Type & Default value|Description|Example values|
|----|----|----|----|
| id| string; optional|id of component used to identify dash components in callbacks| |
|interval| number; default 1000| This component will increment the counter `n_intervals` every `interval` milliseconds| |
|disabled |boolean; optional| If True, the n_interval counter and the timer no longer updates. This pauses the timer.| |
|n_intervals| number; default 0| Number of times the interval has passed (read-only)| |
|max_intervals| number; default -1| Number of times the interval will be fired. If -1, then the interval has no limit and if 0 then the interval stops running.||
|timer| number; default 0| When in countdown mode, the timer will count down to zero from the starting `duration` and will show the number of milliseconds remaining. When in stopwatch mode, the timer will count up from zero and show the number of milliseconds elapsed. (read only) | |
|mode| 'stopwatch' or 'countdown'; default 'countdown'| The timer will count down to zero in `countdown` mode and count up from zero in `stopwatch` mode| |
|duration| number; default -1| Sets the number of milliseconds the timer will run. If -1 the timer will not be limited by the duration and if 0 then the timer stops running and may be reset.||
|reset| boolean; default True| This will start the timer at the beginning with the given prop settings.| |
|fire_times| list; optional| A list of the time(s) in milliseconds at which to fire a callback. This can be used to start a task at a given time rather than using the timer. Since the timer is typically set at a small interval like one second, using `fire_times` can reduce the number of times a callback is fired and can increase app performance. The time(s) must be a multiple of the interval.| |
|at_fire_time| number| This is updated when the timer reaches one of the times in the `fire_times` list. Using `at_fire_time` in a callback will trigger the callback at the time(s) in `fire_times` (Read only)| |
|rerun|boolean; default False| When True, the timer repeats once the timer has run for the number of milliseconds set in the `duration`.| |
|messages|dict; optional| Timer messages to be displayed by the component rather than showing the timer. It is a dictionary in the form of: { integer: string} where integer is the time in milliseconds of when the `string` message is to be displayed. Note: `timer_format` will override `messages`.| {10000 : "updating in 10 seconds"} will display the message "updating in 10 seconds" once the timer equals 10000.|
|timer_format|string; optional. One of:| If a timer is displayed, it will override timer `messages`. This formats the timer (milliseconds) into human readable formats.| |
| | 'none'; default| No timer will be displayed. Timer `messages` will be shown.
| | 'display'| Display timer in default format. For example, 1337000000 milliseconds will display as: '15d 11h 23m 20s'|'15d 11h 23m 20s'|
| | 'compact'| Shows a compact timer display. It will only show the first unit| 1h 10m → 1h|
| | 'verbose'| Verbose will display full-length units.|5h 1m 45s → 5 hours 1 minute 45 seconds|
| | 'colonNotation'| Use this when you want to display time without the time units, similar to a digital watch. It will always show at least minutes: 1s → 0:01|5h 1m 45s → 5:01:45|
### Demo
Run `timer_demo_py` to see eight examples using `dcc.Timer`. Some may be good candidates for the docs. Here is a preview:
#### Countdown and Stopwatch timers with messages updated clientside - no callbacks required!

#### Space shuttle app:
This app uses the `dcc.Timer` component to launch the space shuttle. :rocket:
- The `messages` property is used to define the messages that are displayed at certain times during the launch.
- The `fire_times` property specifies the time to trigger a callback to start the launch.
The timer runs for 51 seconds, but it only fires the callback once (at liftoff) All the other messages are handled
clientside by the component.

Ok, thank you but I need this functionality now
So, I implemented my own rudimentary timer callback with desired functionality:
time_interval_s = 120
time_interval_ms = time_interval_s * 1000
...
@app.callback(
Output("timer_display", "children"),
Input("interval-component", "n_intervals"),
)
def update_output(n):
#calculate remaining time in ms
remaining = time_interval_ms - (n * 100)
minute = (remaining // 60000)
second = (remaining % 60000) // 1000
milisecond = (remaining % 1000) // 10
return u'{:02d}:{:02d}.{:02d}'.format(minute, second, milisecond)
In case someone is looking for a complete working solution over this topic, I have combined the pseudo code provided by @kahlenberg above with working solution by @AnnMarieW from https://community.plotly.com/t/using-dcc-interval-for-continuous-update/41071/10 into the following codes:
import dash
from dash.dependencies import Input, Output, State
import dash_core_components as dcc
import dash_html_components as html
from dash.exceptions import PreventUpdate
external_stylesheets = ["https://codepen.io/chriddyp/pen/bWLwgP.css"]
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
app.layout = html.Div(
[
# "start value",
dcc.Input(id="total", type="number", value=120 * 1000),
# "countdown value", " #can be hidden - or use dcc.Store instead
# dcc.Input(id="countdown", type="number", value=0, disabled=True),
html.Div(id="page-content"),
dcc.Interval(id="interval", n_intervals=0, interval=3000),
]
)
@app.callback(
Output("page-content", "children"),
Input("total", "value"),
Input("interval", "n_intervals"),
)
def display_page(value, n):
if not value:
raise PreventUpdate
if not value:
raise PreventUpdate
ctx = dash.callback_context
callback_input_id = ctx.triggered[0]["prop_id"].split(".")[0]
if callback_input_id == "total":
remaining = value
else:
#calculate remaining time in ms
remaining = value - (n * 100)
minute = (remaining // 60000)
second = (remaining % 60000) // 1000
milisecond = (remaining % 1000) // 10
return u'{:02d}:{:02d}.{:02d}'.format(minute, second, milisecond)
if __name__ == "__main__":
app.run_server(debug=True)
If you would like to see how @kahlenberg pseudo code is functioning.