Skip to content

feat: add fragment rendering support#1216

Merged
a-h merged 7 commits intomainfrom
fragment_support
Jul 20, 2025
Merged

feat: add fragment rendering support#1216
a-h merged 7 commits intomainfrom
fragment_support

Conversation

@a-h
Copy link
Copy Markdown
Owner

@a-h a-h commented Jul 9, 2025

This PR adds fragment rendering support.

It enables an optimisation for HTMX by returning a smaller HTML payload when an entire document is not required. When carrying out a hx-get or similar, if an entire page is returned the hx-select attribute (https://htmx.org/attributes/hx-select/) needs to be used to select the subsection of content to replace. This enables the server to return only the requested content.

The fragment concept is discussed further in https://htmx.org/essays/template-fragments/

I've included a docs update, a HTMX example, tests for the HTTP handler, and a set of generator tests which can further explain the feature.

@a-h a-h requested review from Copilot and joerdav July 9, 2025 08:20
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR implements support for rendering named template fragments, which allows returning only specified parts of a page (useful for HTMX optimisations). It extends the HTTP handler, adds fragment context logic, updates tests, examples, and documentation.

  • Extend ComponentHandler with fragment buffering and streaming paths (WithFragments)
  • Implement Fragment component and context to route output to the correct writer
  • Add unit tests for handler and generator, plus an HTMX example and docs update

Reviewed Changes

Copilot reviewed 13 out of 14 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
handler.go Add FragmentNames field and new render paths (ServeHTTPBufferedFragment, WithFragments)
fragment.go Implement fragment context, Fragment.Render logic
handler_test.go Tests for fragment rendering and streaming
generator/test-fragment/* New templ generator tests and template files
examples/htmx-fragments/* HTMX example template, generated code, Go module, and README
docs/docs/03-syntax-and-usage/19-fragments.md Documentation for fragment feature
Comments suppressed due to low confidence (3)

docs/docs/03-syntax-and-usage/19-fragments.md:27

  • The code sample references templ.WithFragment, but the actual API is templ.WithFragments. Update the sample to use the correct function name.
handler := templ.Handler(Page(), templ.WithFragment("name"))

handler.go:159

  • Update the comment to match the function name and behavior, e.g., WithFragments sets the names of fragments to render.
// WithFragment sets the name of the fragment to render.

@joerdav
Copy link
Copy Markdown
Collaborator

joerdav commented Jul 9, 2025

This looks good! I think this will be very useful!

2 notes:

  • Should we document and define the behavour if 2 fragments exist with the same name?
  • I wonder if it would be useful to have a func RenderFragment(context.Context, templ.Component, string, io.Writer) error to cover the 90% of cases for this feature?

@a-h
Copy link
Copy Markdown
Owner Author

a-h commented Jul 9, 2025

Both brilliant points as always.

Current behaviour in the PR is to render anything with the name, even if there's multiple fragments with the same name. Happy with that?

Agree with the helper function, great idea, would simplify the tests too, I think.

@joerdav
Copy link
Copy Markdown
Collaborator

joerdav commented Jul 9, 2025

Yep, that behaviour was intuitively what I expected when I read the docs, so makes sense!

If we go with the helper function, does it make sense to make the context functions private, shrinking our API surface? Only expose the RenderFragment and WithFragment functions for now?

Maybe to match the other function signatures the helper should actually be:

func RenderFragment(context.Context, io.Writer, templ.Component, string...) error

@joerdav
Copy link
Copy Markdown
Collaborator

joerdav commented Jul 10, 2025

Thinking about uniqueness. I wonder if instead of accepting a string we could accept any? Similar to how context keys work. So then strings can be used, but also custom types can also be used.

type nameFragmentKey struct {}
var NameFrag = nameFragmentKey{}
templ Page() {
  <div>Page Header</div>
  @templ.Fragment(NameFrag) {
    <div>Content of the fragment</div>
  }
}

@a-h
Copy link
Copy Markdown
Owner Author

a-h commented Jul 10, 2025

Great idea @joerdav - it allows people to avoid name conflicts.

@a-h
Copy link
Copy Markdown
Owner Author

a-h commented Jul 11, 2025

I've implemented your suggestions @joerdav.

@a-h a-h merged commit 542b139 into main Jul 20, 2025
9 checks passed
@a-h a-h deleted the fragment_support branch July 20, 2025 12:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants