A drop-in wrapper block that refreshes its content on a schedule — perfect for dashboards, ticket queues, order lists, monitoring screens, and anywhere you want "live-ish" data without WebSockets. Pauses automatically when the browser tab is hidden (saving your backend from pointless calls), fires an immediate refresh when the user returns, and cleans up cleanly on navigation. Pure client-side, no dependencies.
Auto-Refresh is a small block you wrap around any refreshable content. Set an interval, handle its OnRefresh event, and the block calls you every N seconds so you can re-fetch data, refresh aggregates, or update UI. It's the piece every "live dashboard" reinvents, done properly once.
OnRefresh
IsEnabled
.oap
AutoRefresh IntervalSeconds = 30 Content: [your dashboard / list / cards here] Handle OnRefresh: Refresh Data → MyAggregate
That's the whole integration. Drop the block, put your refreshable UI inside its Content placeholder, wire OnRefresh to refresh your data. The block does the timing.
Content
AutoRefresh
IntervalSeconds
30
True
PauseWhenHidden
IsEnabled = False
A dashboard left running on a large monitor for 24 hours would otherwise call your backend 2,880 times a day at a 30-second interval — even if nobody is looking. Modern browsers throttle background timers, but throttling is inconsistent and still allows some traffic through.
PauseWhenHidden = True (the default) makes this a non-issue: refreshes only happen when the user can actually see the content. When they come back, an immediate refresh brings the view up to date. Zero wasted backend cycles, no cost to responsiveness.
PauseWhenHidden = True
Set PauseWhenHidden = False only if you have a specific reason — e.g. a screen driving a physical dashboard where the timer must keep running regardless of focus.
PauseWhenHidden = False
The right interval depends on how quickly your data changes and how expensive the refresh is:
Below ~5 seconds you should reconsider whether you need real-time (WebSockets / SSE) instead. Above ~5 minutes, users generally expect a manual "Refresh" button rather than auto-refresh.
Toggle IsEnabled from any client action to pause and resume:
Screen action PauseRefreshes: AutoRefreshEnabled = False // bound to the block's IsEnabled Screen action ResumeRefreshes: AutoRefreshEnabled = True // resumes with an immediate refresh
This is useful when the user opens a modal, starts editing a form, or does anything where a live refresh would be disruptive.
Add a "Refresh now" button on your screen that runs the same client action as your OnRefresh handler. The user gets manual control, and the auto-refresh keeps working alongside it. No coordination needed.
One block per page. The block manages its state via a single global handle, so placing two AutoRefresh blocks on the same screen would have them clobber each other. For typical use (one dashboard per screen), this is fine. If you need multiple auto-refreshing regions on one screen, either use manual refresh for the extras or wait for v2 (per-instance state).
"Immediate first fire" is intentional but easy to miss. OnRefresh fires twice quickly on load — once from mount, and again after the first interval elapses. That's by design (see section 6), but if you're not expecting it, it can look like a bug.
No built-in loading indicator. The block manages timing, not visuals. If you want a "refreshing…" spinner during the refresh, add it to your OnRefresh handler manually. This keeps the block's visual footprint zero and lets you match your app's design.
OnRefresh doesn't fire.Confirm IsEnabled is true and IntervalSeconds is positive. If you're testing while the tab is in the background, remember PauseWhenHidden will hold refreshes until you focus the tab.
OnRefresh fires twice quickly on load.That's the intentional immediate-first-fire (section 6). It brings your data up to date on mount instead of waiting a full interval.
Refreshes keep firing after I navigated away.The block cleans up on destroy — if you see this, republish and check that your block's On Destroy event is wired to the block's Teardown action. This is the single most important lifecycle step for anything using setInterval.
Teardown
setInterval
Multiple blocks on the same screen conflict.Known v1 limitation (section 11). Use one AutoRefresh per screen for now.
My backend gets slammed even though the tab is hidden.Confirm PauseWhenHidden = True (it's the default). If it's off, refreshes continue in the background.
Published on the OutSystems Forge as open, reusable code. Free to use and adapt in your OutSystems projects.