diff --git a/gomponents.go b/gomponents.go index 7b73a3b..cb59964 100644 --- a/gomponents.go +++ b/gomponents.go @@ -254,9 +254,47 @@ func Group(children []Node) Node { // If condition is true, return the given Node. Otherwise, return nil. // This helper function is good for inlining elements conditionally. +// This doesn't behave entirely like a regular if statement, because nested Nodes and their parameters are evaluated +// from the deepest level and up before hitting If (because that's how Go works). +// If you need lazy evaluation of the given Node, see Lazy. func If(condition bool, n Node) Node { if condition { return n } return nil } + +// Lazy returns a Node which calls the given callback function only when rendered. +// Used with If, it enables lazy evaluation of the node to return, depending on the condition passed to If. +// It defaults to being an ElementType, but can be set to AttributeType by passing a NodeType. +// Even though nodeType is variadic, only the first NodeType is used. +func Lazy(cb func() Node, nodeType ...NodeType) Node { + if cb == nil { + panic("lazy callback cannot be nil") + } + + switch len(nodeType) { + case 0: + return &lazy{CB: cb} + case 1: + return &lazy{CB: cb, T: nodeType[0]} + default: + panic("lazy only accepts one node type") + } +} + +// Lazy is returned by Lazy. +type lazy struct { + CB func() Node + T NodeType +} + +// Render satisfies Node. +func (l *lazy) Render(w io.Writer) error { + return l.CB().Render(w) +} + +// Type satisfies nodeTypeDescriber. +func (l *lazy) Type() NodeType { + return l.T +} diff --git a/gomponents_test.go b/gomponents_test.go index 32304f3..c0b22de 100644 --- a/gomponents_test.go +++ b/gomponents_test.go @@ -284,3 +284,64 @@ func ExampleIf() { _ = e.Render(os.Stdout) // Output: