Skip to main content

ITurboStreamBuilder Interface

Builder interface for constructing Turbo Stream actions. Provides a fluent API for building DOM updates that are sent to clients.

Namespace​

Tombatron.Turbo

Methods​

All methods return the builder instance for method chaining.

Append(string target, string html)​

Appends content to the end of the target element's children.

builder.Append("notifications", "<div class='notification'>New message</div>");

Generated HTML:

<turbo-stream action="append" target="notifications">
<template><div class='notification'>New message</div></template>
</turbo-stream>

Prepend(string target, string html)​

Prepends content to the beginning of the target element's children.

builder.Prepend("activity-feed", "<div class='activity'>User logged in</div>");

Replace(string target, string html, bool morph = false)​

Replaces the entire target element with the provided content.

builder.Replace("user-card", "<div id='user-card'>Updated Card</div>");

When morph is true, Turbo uses DOM morphing (via idiomorph) to update the element, preserving DOM state such as form inputs, focus, and scroll positions:

builder.Replace("user-card", "<div id='user-card'>Updated Card</div>", morph: true);

Generated HTML with morph:

<turbo-stream action="replace" method="morph" target="user-card">
<template><div id='user-card'>Updated Card</div></template>
</turbo-stream>

Important: When using Replace, include the target element's ID in the replacement HTML if you want to target it again later.

Update(string target, string html, bool morph = false)​

Updates the inner content of the target element without replacing the element itself.

builder.Update("cart-total", "$149.99");

When morph is true, Turbo uses DOM morphing to intelligently diff and patch the inner content:

builder.Update("product-list", newListHtml, morph: true);

This is the most commonly used action for updating text or simple content.

Remove(string target)​

Removes the target element from the DOM entirely.

builder.Remove("item-123");

Before(string target, string html)​

Inserts content immediately before the target element (as a sibling).

builder.Before("add-item-button", "<div class='item'>New Item</div>");

After(string target, string html)​

Inserts content immediately after the target element (as a sibling).

builder.After("item-5", "<div class='item'>Item 6</div>");

Refresh(string? requestId = null)​

Tells clients to perform a page refresh. Optionally includes a request ID so the originating client can suppress the redundant refresh.

Parameters:

  • requestId — The X-Turbo-Request-Id of the originating request, or null for no suppression
builder.Refresh();
builder.Refresh(requestId: "abc-123");

Generated HTML:

<turbo-stream action="refresh"></turbo-stream>
<turbo-stream action="refresh" request-id="abc-123"></turbo-stream>

Note: The Refresh action does not use a <template> or target — it triggers a full page re-fetch. To configure morphing and scroll preservation for page refreshes, use the <turbo-meta> tag helper in your layout's <head>. For convenience, see also ITurbo.StreamRefresh() and ITurbo.BroadcastRefresh().

CSS Selector Targeting​

The *All methods work like their single-target counterparts but use a CSS selector via the targets attribute (plural) instead of a DOM ID via target. This lets you update multiple elements in one action.

AppendAll(string targets, string html)​

Appends content to the end of all elements matching the CSS selector.

builder.AppendAll(".notification-list", "<div class='notification'>New alert</div>");

Generated HTML:

<turbo-stream action="append" targets=".notification-list">
<template><div class='notification'>New alert</div></template>
</turbo-stream>

PrependAll(string targets, string html)​

Prepends content to the beginning of all elements matching the CSS selector.

builder.PrependAll(".feed", "<div class='entry'>Latest event</div>");

ReplaceAll(string targets, string html, bool morph = false)​

Replaces all elements matching the CSS selector with the provided content.

builder.ReplaceAll(".stale-card", "<div class='card'>Refreshed</div>");
builder.ReplaceAll(".stale-card", "<div class='card'>Refreshed</div>", morph: true);

UpdateAll(string targets, string html, bool morph = false)​

Updates the inner content of all elements matching the CSS selector.

builder.UpdateAll(".price", "$9.99");
builder.UpdateAll(".price", "$9.99", morph: true);

RemoveAll(string targets)​

Removes all elements matching the CSS selector from the DOM.

builder.RemoveAll(".dismissed");

Generated HTML:

<turbo-stream action="remove" targets=".dismissed"></turbo-stream>

BeforeAll(string targets, string html)​

Inserts content immediately before all elements matching the CSS selector.

builder.BeforeAll(".section-header", "<hr class='divider'>");

AfterAll(string targets, string html)​

Inserts content immediately after all elements matching the CSS selector.

builder.AfterAll(".item", "<div class='separator'></div>");

Build()​

Builds the final Turbo Stream HTML containing all configured actions. This is called internally by ITurbo.Stream() and typically doesn't need to be called directly.

string html = builder.Build();

Method Chaining​

All action methods can be chained together:

await _turbo.Stream("user:123", builder =>
{
builder
.Append("notifications", "<div>Order confirmed!</div>")
.Update("cart-count", "0")
.Remove("checkout-button")
.Replace("cart-summary", "<div id='cart-summary'>Cart is empty</div>");
});

Action Summary​

ActionTarget ElementContentMorph Support
AppendPreservedAdded as last childNo
PrependPreservedAdded as first childNo
ReplaceRemovedReplaces entire elementYes
UpdatePreservedReplaces inner contentYes
RemoveRemovedN/ANo
BeforePreservedAdded before elementNo
AfterPreservedAdded after elementNo
RefreshN/A (full page)N/ANo (use <turbo-meta>)

Each action above (except Refresh) has a corresponding *All variant that accepts a CSS selector via the targets parameter instead of a single DOM ID:

Single TargetCSS Selector
Append(target, html)AppendAll(targets, html)
Prepend(target, html)PrependAll(targets, html)
Replace(target, html, morph)ReplaceAll(targets, html, morph)
Update(target, html, morph)UpdateAll(targets, html, morph)
Remove(target)RemoveAll(targets)
Before(target, html)BeforeAll(targets, html)
After(target, html)AfterAll(targets, html)

Validation​

All methods validate their parameters:

  • target cannot be null, empty, or whitespace
  • targets (CSS selector) cannot be null, empty, or whitespace
  • html cannot be null (except for Remove/RemoveAll)

Invalid parameters throw ArgumentNullException or ArgumentException.

See Also​