mirror of
https://github.com/a-h/templ.git
synced 2025-02-06 09:45:21 +00:00
65 lines
1.7 KiB
Go
65 lines
1.7 KiB
Go
package templ
|
|
|
|
import (
|
|
"context"
|
|
"io"
|
|
"sync/atomic"
|
|
)
|
|
|
|
// 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(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
|
|
// rendered once per context.
|
|
type OnceHandle struct {
|
|
// id is used to identify which instance of the OnceHandle is being used.
|
|
// The OnceHandle can't be an empty struct, because:
|
|
//
|
|
// | Two distinct zero-size variables may
|
|
// | have the same address in memory
|
|
//
|
|
// 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.
|
|
func (o *OnceHandle) Once() Component {
|
|
return ComponentFunc(func(ctx context.Context, w io.Writer) (err error) {
|
|
_, v := getContext(ctx)
|
|
if v.getHasBeenRendered(o) {
|
|
return nil
|
|
}
|
|
v.setHasBeenRendered(o)
|
|
if o.c != nil {
|
|
return o.c.Render(ctx, w)
|
|
}
|
|
return GetChildren(ctx).Render(ctx, w)
|
|
})
|
|
}
|