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