SwapResponse - Multi-Target Updates
Update multiple parts of your page with a single HTTP response.
Overview
SwapResponse enables you to update multiple UI elements, show toasts, trigger client events, and coordinate complex UIs with a single, fluent API call.
One HTTP request. Multiple UI updates. Zero JavaScript.
Basic Usage
[HttpPost]
public IActionResult UpdateProduct(Product product)
{
_productService.Update(product);
return SwapResponse()
.WithView("_ProductCard", product)
.WithSuccessToast("Product updated!")
.Build();
}
Multi-Target Updates
Update several page elements at once:
[HttpPost]
public IActionResult AddToCart(int productId)
{
var cart = _cartService.AddProduct(productId);
var product = _productService.GetById(productId);
return SwapResponse()
.WithView("_ProductCard", product) // Update main content
.AlsoUpdate("cart-count", "_CartCount", cart.ItemCount) // Update header badge
.AlsoUpdate("cart-preview", "_CartPreview", cart) // Update cart dropdown
.WithSuccessToast("Added to cart!")
.Build();
}
View structure:
<!-- Main content area (default target) -->
<div id="product-card">
@await Html.PartialAsync("_ProductCard", Model)
</div>
<!-- Header cart count -->
<span id="cart-count">@ViewBag.CartCount</span>
<!-- Cart dropdown -->
<div id="cart-preview">
@await Html.PartialAsync("_CartPreview", CartModel)
</div>
Toast Notifications
Show feedback without extra HTML:
// Success toast
return SwapResponse()
.WithView("_Form", model)
.WithSuccessToast("Saved successfully!")
.Build();
// Error toast
return SwapResponse()
.WithView("_Form", model)
.WithErrorToast("Something went wrong")
.Build();
// Info/Warning toasts
.WithInfoToast("Processing...")
.WithWarningToast("Almost full")
Out-of-Band (OOB) Swaps
Update elements outside the main target using HTMX's OOB feature:
return SwapResponse()
.WithView("_ProductList", products)
.WithOobSwap("notification-badge", "_NotificationBadge", notificationCount)
.Build();
The OOB element will be updated anywhere on the page, even if it's not in the main target area.
Triggering Client Events
Coordinate with JavaScript when needed:
return SwapResponse()
.WithView("_Modal", model)
.TriggerClientEvent("modalOpened", new { modalId = "product-modal" })
.Build();
Listen on the client:
document.body.addEventListener('modalOpened', function(event) {
console.log('Modal opened:', event.detail.modalId);
});
HTTP Headers
Control HTMX behavior via response headers:
return SwapResponse()
.WithView("_Product", product)
.PushUrl($"/products/{product.Id}") // Update browser URL
.Build();
// Or redirect
return SwapResponse()
.WithView("_Success", model)
.Redirect("/products")
.Build();
Chaining Methods
All methods are chainable for readability:
return SwapResponse()
.WithView("_OrderConfirmation", order)
.AlsoUpdate("cart-count", "_CartCount", 0)
.AlsoUpdate("user-credits", "_Credits", user.Credits)
.WithSuccessToast($"Order #{order.Id} placed!")
.TriggerClientEvent("orderPlaced", order)
.PushUrl($"/orders/{order.Id}")
.Build();
Error Handling
Handle validation errors gracefully:
[HttpPost]
public IActionResult Create([FromForm] ProductModel model)
{
if (!ModelState.IsValid)
{
return SwapResponse()
.WithView("_ProductForm", model)
.WithErrorToast("Please fix the errors")
.Build();
}
// ... save product
}
Performance Tips
- Batch updates: Use
SwapResponseto send multiple updates in one request instead of multiple AJAX calls - Keep partials small: Each
AlsoUpdate()renders a partial—keep them focused - Use Source Generators: Type-safe element IDs prevent runtime errors
Related
- SwapView - Basic view rendering
- Event System - Decoupled UI coordination
- Forms Guide - Form submission patterns