Skip to content

Commit 3c65b43

Browse files
Quarkz14a-h
andauthoredSep 30, 2024··
feat: templ.Join method renders multiple components into a single component (#929)
Co-authored-by: Adrian Hesketh <adrianhesketh@hushmail.com>
1 parent e59640f commit 3c65b43

File tree

3 files changed

+137
-0
lines changed

3 files changed

+137
-0
lines changed
 

‎docs/docs/03-syntax-and-usage/10-template-composition.md

+37
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,43 @@ func main() {
236236
</div>
237237
```
238238

239+
## Joining Components
240+
241+
Components can be aggregated into a single Component using `templ.Join`.
242+
243+
```templ
244+
package main
245+
246+
templ hello() {
247+
<span>hello</span>
248+
}
249+
250+
templ world() {
251+
<span>world</span>
252+
}
253+
254+
templ helloWorld() {
255+
@templ.Join(hello(), world())
256+
}
257+
```
258+
259+
```go title="main.go"
260+
package main
261+
262+
import (
263+
"context"
264+
"os"
265+
)
266+
267+
func main() {
268+
helloWorld().Render(context.Background(), os.Stdout)
269+
}
270+
```
271+
272+
```html title="output"
273+
<span>hello</span><span>world</span>
274+
```
275+
239276
## Sharing and re-using components
240277

241278
Since templ components are compiled into Go functions by the `go generate` command, templ components follow the rules of Go, and are shared in exactly the same way as Go code.

‎join.go

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package templ
2+
3+
import (
4+
"context"
5+
"io"
6+
)
7+
8+
// Join returns a single `templ.Component` that will render provided components in order.
9+
// If any of the components return an error the Join component will immediately return with the error.
10+
func Join(components ...Component) Component {
11+
return ComponentFunc(func(ctx context.Context, w io.Writer) (err error) {
12+
for _, c := range components {
13+
if err = c.Render(ctx, w); err != nil {
14+
return err
15+
}
16+
}
17+
return nil
18+
})
19+
}

‎join_test.go

+81
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
package templ_test
2+
3+
import (
4+
"bytes"
5+
"context"
6+
"errors"
7+
"io"
8+
"testing"
9+
10+
"github.com/a-h/templ"
11+
"github.com/google/go-cmp/cmp"
12+
)
13+
14+
func TestJoin(t *testing.T) {
15+
compErr := errors.New("component error")
16+
17+
hello := templ.ComponentFunc(func(ctx context.Context, w io.Writer) error {
18+
if _, err := io.WriteString(w, "Hello"); err != nil {
19+
t.Fatalf("failed to write string: %v", err)
20+
}
21+
return nil
22+
})
23+
world := templ.ComponentFunc(func(ctx context.Context, w io.Writer) error {
24+
if _, err := io.WriteString(w, "World"); err != nil {
25+
t.Fatalf("failed to write string: %v", err)
26+
}
27+
return nil
28+
})
29+
err := templ.ComponentFunc(func(ctx context.Context, w io.Writer) error {
30+
return compErr
31+
})
32+
33+
tests := []struct {
34+
name string
35+
input []templ.Component
36+
expectedOutput string
37+
expectedErr error
38+
}{
39+
{
40+
name: "a nil slice of components produces no output",
41+
input: nil,
42+
expectedOutput: "",
43+
},
44+
{
45+
name: "an empty list of components produces no output",
46+
input: []templ.Component{},
47+
expectedOutput: "",
48+
},
49+
{
50+
name: "components are rendered in order",
51+
input: []templ.Component{hello, world},
52+
expectedOutput: "HelloWorld",
53+
},
54+
{
55+
name: "components are rendered in order, and errors returned",
56+
input: []templ.Component{hello, err},
57+
expectedOutput: "Hello",
58+
expectedErr: compErr,
59+
},
60+
{
61+
name: "no further components are rendered after an error",
62+
input: []templ.Component{err, hello},
63+
expectedOutput: "",
64+
expectedErr: compErr,
65+
},
66+
}
67+
68+
for _, tt := range tests {
69+
t.Run(tt.name, func(t *testing.T) {
70+
got := templ.Join(tt.input...)
71+
b := new(bytes.Buffer)
72+
err := got.Render(context.Background(), b)
73+
if err != tt.expectedErr {
74+
t.Fatalf("failed to render component: %v", err)
75+
}
76+
if diff := cmp.Diff(tt.expectedOutput, b.String()); diff != "" {
77+
t.Error(diff)
78+
}
79+
})
80+
}
81+
}

0 commit comments

Comments
 (0)
Please sign in to comment.