Heimdall Docs

Triggers

Triggers define when a Heimdall interaction begins. They are the browser-side start of the request, response, and swap cycle.

A trigger answers one question only: when should this element invoke the server?

1. What a Trigger Means in Heimdall

A trigger is the event boundary that starts an interaction. It does not define payload shape, response structure, or swap behavior by itself. It simply tells the runtime when to begin.

Trigger
-> payload is gathered
-> action is invoked
-> HTML is returned
-> swap is applied

2. The Core Pattern

In Heimdall, triggers are always attached through the behavior layer. That keeps HTML structure and Heimdall interaction behavior conceptually separate.

button.Heimdall()
    .Click("Counter.Increment")
    .PayloadFromClosestState()
    .SwapOuter();

3. Why Triggers Matter

Heimdall interactions are built from small, explicit pieces. The trigger is the first of those pieces. It gives the browser a precise point at which server-driven UI should continue.

A trigger starts the interaction.
Payload binding decides what data is sent.
The action decides what HTML to return.
The swap decides how that HTML is applied.

4. Click

The click trigger is the most common starting point. It is a natural fit for buttons, links, and small interaction surfaces that should invoke the server when selected.

Strongly Typed Setup

button.Heimdall()
    .Click("Counter.Increment")
    .PayloadFromClosestState()
    .SwapOuter();

Rendered HTML Mental Model

<button
  data-heimdall-click="Counter.Increment"
  data-heimdall-payload="closest-state"
  data-heimdall-swap="outer">
  Increment
</button>

5. Submit

Submit is the form-native trigger. It works especially well when the form itself is the payload boundary and when native browser validation should remain part of the interaction.

form.Heimdall()
    .OnSubmit("Contact.Submit")
    .PayloadFromClosestForm()
    .SwapNone();

This is one of the clearest examples of Heimdall working with normal HTML rather than replacing it.

<form
  data-heimdall-submit="Contact.Submit"
  data-heimdall-payload="closest-form"
  data-heimdall-swap="none">
  ...
</form>

6. Input

The input trigger fires as the user types. It is useful for live search, server-driven suggestions, and immediate validation feedback.

input.Heimdall()
    .Input("Search.Query")
    .PayloadFromClosestForm()
    .Target("#search-results")
    .SwapInner();

Because input can fire frequently, it is usually best reserved for interactions where continuous feedback is worth the extra request volume.

7. Change

The change trigger is lower-frequency than input. It is a good fit when the interaction should wait until a selection or value change is committed.

select.Heimdall()
    .Change("Reports.Filter")
    .PayloadFromClosestForm()
    .Target("#report-results")
    .SwapInner();

This often works well for select elements, toggles, or filter controls where per-keystroke updates are unnecessary.

8. Keydown

The keydown trigger fires in response to keyboard input. It is useful when a keypress itself is the interaction boundary rather than a full field change or submit.

input.Heimdall()
    .KeyDown("Search.Accept")
    .PayloadFromClosestForm()
    .Target("#search-results")
    .SwapInner();

This is often useful for keyboard-driven UI, quick actions, or flows where specific keys should initiate a request.

9. Blur

The blur trigger fires when an element loses focus. It is a natural fit for validation or post-edit checks that should happen after the user leaves a field.

input.Heimdall()
    .Blur("Profile.ValidateDisplayName")
    .PayloadFromClosestForm()
    .Target("#display-name-validation")
    .SwapInner();

This keeps feedback tied to the end of a field interaction rather than to every keystroke.

10. Hover

The hover trigger fires when an element is hovered. It can be useful for previews, hints, or secondary content that should appear only when the user pauses over a boundary.

div.Heimdall()
    .Hover("Products.Preview")
    .PayloadFromClosestState("product")
    .Target("#product-preview")
    .SwapInner();

Hover is best used intentionally, especially when preview content is valuable but should not be loaded up front.

11. Visible

The visible trigger fires when an element becomes visible in the viewport. This is the foundation of lazy loading and continuation-boundary patterns.

sentinel.Heimdall()
    .Visible("Weather.LoadMore")
    .PayloadFromClosestState("weather")
    .Target("#weather-sentinel")
    .SwapOuter();

12. Scroll

The scroll trigger fires as a scroll boundary is reached. It is useful when interaction should be tied to scroll position rather than simple visibility.

div.Heimdall()
    .Scroll("Activity.LoadEarlier")
    .PayloadFromClosestState("activity")
    .Target("#activity-stream")
    .SwapInner();

This can be useful for feeds, activity timelines, or UI that should react to scrolling through a region.

13. Load

The load trigger fires when an element is loaded into the DOM. It is useful when content should be requested immediately as part of initial rendering, but still through the normal Heimdall action pipeline.

div.Heimdall()
    .Load("Dashboard.Summary")
    .Target("#summary-panel")
    .SwapInner();

This can be useful for panels, widgets, or deferred sections that should begin empty and hydrate through a standard action.

14. Trigger Does Not Mean Behavior by Itself

A trigger does not fully describe an interaction. It only defines the moment the interaction begins. The rest still comes from payload binding, target selection, and swap rules.

Trigger = when
Payload = what data is sent
Target = where response lands
Swap = how response is applied

15. Why Heimdall Keeps Triggers Explicit

Heimdall stays clear by making interaction boundaries visible in the markup. Instead of hiding behavior behind a large client abstraction, the DOM itself expresses what event starts the request.

The interaction start is visible on the element.
The trigger does not need its own client-side state system.
The same trigger model works across buttons, forms, sentinels, deferred regions, and keyboard-driven UI.
The browser remains a small runtime rather than a second application.

16. When to Use Which Trigger

Each trigger fits a different interaction shape.

Click    -> buttons, links, explicit actions
Submit   -> forms, native validation, traditional submits
Input    -> live search, instant validation, live suggestions
Change   -> committed field updates, select controls, filters
Keydown  -> keyboard-driven actions, key-based flows
Blur     -> post-edit validation, field completion checks
Hover    -> previews, hints, deferred secondary UI
Visible  -> lazy loading, continuation boundaries
Scroll   -> feed or timeline interaction tied to scroll position
Load     -> deferred initial content, startup widgets