Skip to main content

CountdownRenderer

Reference

  • The CountdownRenderer component displays a live (or static) countdown/delay indicator for a DateTime attribute value.
  • It shows the calendar-aware time remaining until (or elapsed past) a target date, optionally comparing the attribute's own value against another DateTime attribute on the same instance.
  • If the resolved target date is invalid or missing, it falls back to rendering the value with FormattedDateTime.
  • This is the same renderer used internally when a DateTime attribute's renderer is set to DelayCountdownRenderer, exposed here for use in custom widgets.

Props

  • value: the attribute's own date value (ISO date-time string).
  • config: attribute configuration object, including:
    • formatConditions: conditional formatting rules, same shape used by grid conditional formatting. See Styling below.
    • rendererSettings:
      • liveCountdown (boolean, default true): ticks every second when enabled; otherwise renders a static diff computed once.
      • compareAgainstAttribute (string): name of another DateTime attribute on the row to use as the target date instead of value.
      • countdownPrefix (string): text shown before the countdown value when the target date is in the future.
      • delayPrefix (string): text shown before the countdown value when the target date is overdue.
  • style: an optional static inline style object for the countdown container. See Styling below.
  • options: row/instance context. See Options below.

Styling

CountdownRenderer supports styling the same way conditional formatting works elsewhere in Protrak, with one extra behavior because the value ticks over time:

  • Static style — pass style directly (e.g. { color: 'blue', fontWeight: 'bold' }). This is used as-is whenever there is no live conditional formatting to override it.
  • Live conditional formatting — if config.formatConditions is set and liveCountdown is true (the default), the renderer re-evaluates the formatting rules against options on every tick (every second), the same way the grid evaluates formatConditions for a row. This lets a style change automatically as time passes — e.g. switch to a red background the moment a countdown becomes overdue — without the parent widget needing to re-render or recompute anything.
  • When a live-evaluated style is produced, it takes priority over the style prop. If you only want a static style, either omit formatConditions from config or set rendererSettings.liveCountdown to false.
  • Evaluating formatConditions requires the same row/tenant context described under options.versionDetails/options.currentInstance and options.settings below — rules that reference attribute or user values won't match if that context isn't passed in.

Options

options mirrors the context the grid/attribute pipeline normally supplies, so passing the equivalent shape from a custom widget makes all renderer behavior (target comparison, tooltip formatting, live conditional formatting) work the same way:

  • options.versionDetails (falls back to options.currentInstance if not set): the row/instance data object, shaped as { attributes: [{ name, dateValue, ... }], ...otherInstanceFields }. Used to:
    • resolve rendererSettings.compareAgainstAttribute — looked up by matching name in attributes.
    • act as the row data passed into formatConditions rule evaluation (see Styling).
  • options.settings.settings.dateTimeFormat: { timeFormat, dateFormat, utcOffset, timeZoneId } — tenant date/time format, used to render the full target date-time shown in the hover tooltip, and passed through as part of the settings object used to evaluate formatConditions.
  • options.settings.userData: consumed by formatConditions rules that check against the current user (e.g. a rule scoped to "assigned to me").
  • If options (or parts of it) are omitted, the renderer falls back to safe defaults (UTC offset +00:00, no timezone, empty user data) — compareAgainstAttribute and user/attribute-based formatConditions simply won't resolve without the real context.

Usage

const { protrakComponents } = React.useContext(customWidgetContext);
const { CountdownRenderer } = protrakComponents;

//Example of config property, with live conditional formatting on overdue:
const config = {
"fieldType": "Attribute",
"attributeType": "DateTime",
"label": "Due Date",
"attributeName": "ADueDate",
"renderer": "DelayCountdownRenderer",
"rendererSettings": {
"liveCountdown": true,
"compareAgainstAttribute": "ACompletionDate",
"countdownPrefix": "Remaining",
"delayPrefix": "Overdue"
},
"formatConditions": [
{
"rule": { "rules": [ /* same rule shape as grid conditional formatting */ ] },
"style": "background-color:#ffcccc;"
}
]
}

//Example of options property, shaped like the context passed to attribute renderers generally:
const options = {
"typeName": "Project",
"instanceId": "<instance-guid>",
// the row data; each attribute is a top-level key on versionDetails
"versionDetails": {
"ADueDate": { "name": "ADueDate", "type": "DateTime", "dateValue": "2026-02-01T00:00:00.000Z" },
"ACompletionDate": { "name": "ACompletionDate", "type": "DateTime", "dateValue": null }
},
"customStyle": { "backgroundColor": "#fbe5e5", "color": "#cc2424" },
"currentInstance": null, //instance data
"settings": {
"settings": {
"dateTimeFormat": {
"dateFormat": "dd-MM-yyyy",
"timeFormat": "hmsa",
"timeZoneId": "Asia/Kolkata",
"utcOffset": "+05:30"
}
},
"userData": { "userId": "<user-guid>", "name": "Sample User" }
}
}

return (
<CountdownRenderer
value={value}
config={config}
style={{ backgroundColor: '#fbe5e5', color: '#cc2424' }} // static fallback style; overridden by formatConditions when they match
options={options}
/>
);
// pass the attribute's value, its config, an optional static style, and row/options context

UI

CountdownRenderer