1
0
mirror of https://github.com/a-h/templ.git synced 2025-02-06 09:45:21 +00:00

refactor: add neater support for code components into templ.Once (#755)

This commit is contained in:
Adrian Hesketh 2024-05-25 09:13:06 +01:00 committed by GitHub
parent 30091610f5
commit 3d154ff737
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 35 additions and 3 deletions

View File

@ -1 +1 @@
0.2.702
0.2.705

25
once.go
View File

@ -9,12 +9,27 @@ import (
// onceHandleIndex is used to identify unique once handles in a program run.
var onceHandleIndex int64
type OnceOpt func(*OnceHandle)
// WithOnceComponent sets the component to be rendered once per context.
// This can be used instead of setting the children of the `Once` method,
// for example, if creating a code component outside of a templ HTML template.
func WithComponent(c Component) OnceOpt {
return func(o *OnceHandle) {
o.c = c
}
}
// NewOnceHandle creates a OnceHandle used to ensure that the children of its
// `Once` method are only rendered once per context.
func NewOnceHandle() *OnceHandle {
return &OnceHandle{
func NewOnceHandle(opts ...OnceOpt) *OnceHandle {
oh := &OnceHandle{
id: atomic.AddInt64(&onceHandleIndex, 1),
}
for _, opt := range opts {
opt(oh)
}
return oh
}
// OnceHandle is used to ensure that the children of its `Once` method are are only
@ -28,6 +43,9 @@ type OnceHandle struct {
//
// https://go.dev/ref/spec#Size_and_alignment_guarantees
id int64
// c is the component to be rendered once per context.
// if c is nil, the children of the `Once` method are rendered.
c Component
}
// Once returns a component that renders its children once per context.
@ -38,6 +56,9 @@ func (o *OnceHandle) Once() Component {
return nil
}
v.setHasBeenRendered(o)
if o.c != nil {
return o.c.Render(ctx, w)
}
return GetChildren(ctx).Render(ctx, w)
})
}

View File

@ -103,4 +103,15 @@ func TestOnceHandle(t *testing.T) {
t.Errorf("unexpected diff:\n%v", diff)
}
})
t.Run("a handle can be used to render a specific component", func(t *testing.T) {
ctx := templ.WithChildren(context.Background(), templ.Raw("child"))
o := templ.NewOnceHandle(templ.WithComponent(templ.Raw("c"))).Once()
var w strings.Builder
if err := o.Render(ctx, &w); err != nil {
t.Fatalf("unexpected error: %v", err)
}
if diff := cmp.Diff("c", w.String()); diff != "" {
t.Errorf("unexpected diff:\n%v", diff)
}
})
}