-
-
Notifications
You must be signed in to change notification settings - Fork 280
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: templ.Join method renders multiple components into a single com…
…ponent (#929) Co-authored-by: Adrian Hesketh <adrianhesketh@hushmail.com>
- Loading branch information
Showing
3 changed files
with
137 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
package templ | ||
|
||
import ( | ||
"context" | ||
"io" | ||
) | ||
|
||
// Join returns a single `templ.Component` that will render provided components in order. | ||
// If any of the components return an error the Join component will immediately return with the error. | ||
func Join(components ...Component) Component { | ||
return ComponentFunc(func(ctx context.Context, w io.Writer) (err error) { | ||
for _, c := range components { | ||
if err = c.Render(ctx, w); err != nil { | ||
return err | ||
} | ||
} | ||
return nil | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
package templ_test | ||
|
||
import ( | ||
"bytes" | ||
"context" | ||
"errors" | ||
"io" | ||
"testing" | ||
|
||
"github.com/a-h/templ" | ||
"github.com/google/go-cmp/cmp" | ||
) | ||
|
||
func TestJoin(t *testing.T) { | ||
compErr := errors.New("component error") | ||
|
||
hello := templ.ComponentFunc(func(ctx context.Context, w io.Writer) error { | ||
if _, err := io.WriteString(w, "Hello"); err != nil { | ||
t.Fatalf("failed to write string: %v", err) | ||
} | ||
return nil | ||
}) | ||
world := templ.ComponentFunc(func(ctx context.Context, w io.Writer) error { | ||
if _, err := io.WriteString(w, "World"); err != nil { | ||
t.Fatalf("failed to write string: %v", err) | ||
} | ||
return nil | ||
}) | ||
err := templ.ComponentFunc(func(ctx context.Context, w io.Writer) error { | ||
return compErr | ||
}) | ||
|
||
tests := []struct { | ||
name string | ||
input []templ.Component | ||
expectedOutput string | ||
expectedErr error | ||
}{ | ||
{ | ||
name: "a nil slice of components produces no output", | ||
input: nil, | ||
expectedOutput: "", | ||
}, | ||
{ | ||
name: "an empty list of components produces no output", | ||
input: []templ.Component{}, | ||
expectedOutput: "", | ||
}, | ||
{ | ||
name: "components are rendered in order", | ||
input: []templ.Component{hello, world}, | ||
expectedOutput: "HelloWorld", | ||
}, | ||
{ | ||
name: "components are rendered in order, and errors returned", | ||
input: []templ.Component{hello, err}, | ||
expectedOutput: "Hello", | ||
expectedErr: compErr, | ||
}, | ||
{ | ||
name: "no further components are rendered after an error", | ||
input: []templ.Component{err, hello}, | ||
expectedOutput: "", | ||
expectedErr: compErr, | ||
}, | ||
} | ||
|
||
for _, tt := range tests { | ||
t.Run(tt.name, func(t *testing.T) { | ||
got := templ.Join(tt.input...) | ||
b := new(bytes.Buffer) | ||
err := got.Render(context.Background(), b) | ||
if err != tt.expectedErr { | ||
t.Fatalf("failed to render component: %v", err) | ||
} | ||
if diff := cmp.Diff(tt.expectedOutput, b.String()); diff != "" { | ||
t.Error(diff) | ||
} | ||
}) | ||
} | ||
} |