Skip to content

Commit

Permalink
refactor: add neater support for code components into templ.Once (#755)
Browse files Browse the repository at this point in the history
  • Loading branch information
a-h authored May 25, 2024
1 parent 3009161 commit 3d154ff
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 3 deletions.
2 changes: 1 addition & 1 deletion .version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.2.702
0.2.705
25 changes: 23 additions & 2 deletions once.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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.
Expand All @@ -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)
})
}
11 changes: 11 additions & 0 deletions once_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
})
}

0 comments on commit 3d154ff

Please sign in to comment.