Heimdall Docs

Polling

Polling lets the Heimdall runtime invoke the server repeatedly over time without requiring a fresh user event each time. It is useful when a region should refresh on an interval but still participate in the normal HTML-over-the-wire pipeline.

A trigger starts because of a browser event. Polling starts again because time has passed.

1. What Polling Means in Heimdall

Polling is repeated runtime-driven invocation of a Heimdall action on an interval. It is not a new user event trigger like click or input. Instead, it reuses the normal action pipeline on a timer.

time passes
-> runtime invokes the action again
-> HTML is returned
-> swap is applied
-> the cycle continues while the element remains active

2. The Core Pattern

In the runtime, polling is expressed through the fluent API and rendered as the heimdall-poll attribute. It works together with a load action on the same element. The load action defines what to invoke. The poll interval defines how often to invoke it again.

panel.Heimdall()
	.Load("Dashboard.Refresh")
	.PayloadFromClosestState("dashboard")
	.PollMs(5000)
	.Target("#dashboard-panel")
	.SwapOuter();

3. Why Polling Matters

Some UI regions are not driven by a direct user action. Status panels, dashboards, queues, and activity summaries often need periodic refresh while still letting the server remain the source of truth.

It keeps refresh behavior inside the normal Heimdall request cycle.
It avoids a separate client-side state synchronization layer.
It lets ordinary HTML regions refresh without special client rendering code.
It keeps the server responsible for what the next UI state should be.

4. Polling Builds on Load

In the current runtime, polling is tied to heimdall-content-load. That means the element already expresses what action should be invoked when it loads, and polling simply repeats that same invocation over time.

Rendered HTML Mental Model

<div
  id="dashboard-panel"
  heimdall-content-load="Dashboard.Refresh"
  heimdall-payload="closest-state:dashboard"
  heimdall-content-target="#dashboard-panel"
  heimdall-content-swap="outer"
  heimdall-poll="5000">
  Loading dashboard...
</div>

If heimdall-poll is present without heimdall-content-load, the runtime warns because there is no action for the interval to invoke.

5. What the Interval Means

The heimdall-poll value is the interval in milliseconds. A value of 5000 means the runtime schedules the next invocation roughly every five seconds while the element remains connected.

heimdall-poll="5000"
-> invoke again about every 5 seconds

6. No Overlapping Requests

The runtime protects a polling boundary from overlapping requests. If one poll tick is still in flight, the next scheduled tick does not start another concurrent invocation on the same element.

poll tick starts
-> request is in flight
-> next tick waits
-> response completes
-> polling continues

That keeps a polling region from stacking duplicate requests when the server or network is slower than the interval.

7. Polling Stops When the Element Is Gone

Polling is attached to an actual DOM boundary. When that element is removed or replaced and is no longer connected, the runtime stops scheduling future ticks for it.

element exists in DOM
-> polling continues

element removed or replaced
-> polling stops

This keeps polling lifecycle aligned with the rendered HTML instead of forcing you to manage a separate timer registry manually.

8. Polling Respects Page Visibility

The runtime skips poll execution while the document is hidden. In practice, that means background tabs do not keep issuing refresh requests on every interval tick.

document visible   -> polling may run
document hidden    -> polling pauses its work
document visible   -> polling resumes on the next interval

That is a small but important runtime behavior because it reduces wasted requests when the user is not actively viewing the page.

9. Polling Still Uses the Normal Interaction Model

Polling changes how often invocation happens, but it does not invent a new transport or rendering model. Payload gathering, target selection, and swap application still work the same way they do for ordinary Heimdall actions.

Polling = timing
Payload = what data is sent
Target  = where HTML lands
Swap    = how HTML is applied

10. A Natural Use Case

Polling is a natural fit for server-owned summary regions where the browser should periodically ask for an updated view.

[ContentInvocation]
public static IHtmlContent Refresh(DashboardState state)
{
    return RenderDashboardPanel(state);
}

The server still decides what has changed. The browser only decides that it is time to ask again.

11. Polling vs Triggers

Polling is easy to confuse with triggers because it causes repeated invocation, but the mental model is different.

Trigger:
- starts because of a browser event
- click, input, submit, visible, and so on

Polling:
- starts again because time passed
- no fresh user event is required

12. Polling vs SSE / Bifrost

Polling asks the server again on an interval. SSE does not ask repeatedly. Instead, the server pushes when it has something to say.

Polling:
- browser asks on a timer

SSE / Bifrost:
- server pushes when ready

13. When Polling Is a Good Fit

Polling works best when periodic staleness is acceptable and when asking again is simpler than maintaining an always-on server push channel.

dashboard summaries
job or queue status
lightweight activity snapshots
panels where 'refresh every few seconds' is good enough

14. Common Mental Model

A useful way to think about polling in Heimdall is that it is a timer attached to a DOM boundary that keeps asking the server for the next HTML truth for that region.

DOM boundary
+ load action
+ poll interval
-> repeated HTML refresh for that boundary

Next Steps

Once polling is clear, the next step is understanding how Heimdall gathers request data for both user-driven and runtime-driven interactions, and then how the browser runtime interprets all of those instructions together.