Skip to content

Some possible alternative ideas for streaming partials #84

@MichaelWest22

Description

@MichaelWest22

Context

I've been working on htmx 4 and recently implemented a streaming partials extension that explores similar territory. I thought there could be some useful ideas to consider as options for this proposal.

Full writeup: Alternative HTML Streaming Patches Design


Key Ideas to Consider

1. Leverage Existing id Attributes

Instead of introducing contentname as a new global attribute, the design could use standard id attributes for targeting:

<!-- Current proposal -->
<div contentname="widget">...</div>
<template contentmethod="replace-children">
  <div contentname="widget">New content</div>
</template>

<!-- Alternative -->
<div id="widget">...</div>
<template for="widget" patchmode="replace-children">
  <div>New content</div>
</template>

Benefits:

  • No new global attributes
  • Works with existing HTML patterns
  • Simpler mental model for developers

2. CSS Selectors for Advanced Targeting

For cases where IDs aren't sufficient or users want to avoid duplicate id issues, CSS selectors provide powerful targeting without new primitives:

<!-- Target by position -->
<template selector=".product-card:nth-child(2)" patchmode="replace-children">
  <div>Updated product</div>
</template>

<!-- Update multiple elements -->
<template selector=".status" patchmode="replace-children" multiple>
  <span>Online</span>
</template>

<!-- Conditional targeting (revision control) -->
<template selector="#content:not([data-revision='v2'])" 
          patchmode="replace-children"
          data-revision="v2">
  <div>New content</div>
</template>

3. Revision Control Without New Attributes

CSS :not() selectors combined with auto-copying data-* attributes from template to target can handle revision control:

<div id="content" data-revision="v1">Content v1</div>

<!-- Only applies if revision differs -->
<template selector="#content:not([data-revision='v2'])" 
          patchmode="replace-children"
          data-revision="v2">
  <div>Content v2</div>
</template>

After patching, the target automatically gets data-revision="v2", preventing duplicate applications. data-* auto-copying would also solve many other client state update tasks:

<template for="submit-btn" patchmode="append" 
          data-loading="true" 
          data-disabled="true">
  <!-- Empty: just copies data-* attributes -->
</template>

4. Potential Future: Upsert Mode

For streaming scenarios where you don't know if an item exists:

<ul id="products">
  <li id="product-1">Product 1 (old)</li>
</ul>

<!-- Updates existing by ID, appends new ones -->
<template selector="#products" patchmode="upsert">
  <li id="product-1">Product 1 (updated)</li>
  <li id="product-2">Product 2 (new)</li>
</template>

Anyway, just some possible ideas to consider. Also created a quick polyfill and demo to show how some of these ideas might work: demo

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions