Skip to main content

Template composition

Templates can be composed using the import expression.

templ showAll() {
@left()
@middle()
@right()
}

templ left() {
<div>Left</div>
}

templ middle() {
<div>Middle</div>
}

templ right() {
<div>Right</div>
}
Output
<div>
Left
</div>
<div>
Middle
</div>
<div>
Right
</div>

Children

Children can be passed to a component for it to wrap.

templ showAll() {
@wrapChildren() {
<div>Inserted from the top</div>
}
}

templ wrapChildren() {
<div id="wrapper">
{ children... }
</div>
}
note

The use of the { children... } expression in the child component.

output
<div id="wrapper">
<div>
Inserted from the top
</div>
</div>

Using children in code components

Children are passed to a component using the Go context. To pass children to a component using Go code, use the templ.WithChildren function.

package main

import (
"context"
"os"

"github.com/a-h/templ"
)

templ wrapChildren() {
<div id="wrapper">
{ children... }
</div>
}

func main() {
contents := templ.ComponentFunc(func(ctx context.Context, w io.Writer) error {
_, err := io.WriteString(w, "<div>Inserted from Go code</div>")
return err
})
ctx := templ.WithChildren(context.Background(), contents)
wrapChildren().Render(ctx, os.Stdout)
}
output
<div id="wrapper">
<div>
Inserted from Go code
</div>
</div>

To get children from the context, use the templ.GetChildren function.

package main

import (
"context"
"os"

"github.com/a-h/templ"
)

func main() {
contents := templ.ComponentFunc(func(ctx context.Context, w io.Writer) error {
_, err := io.WriteString(w, "<div>Inserted from Go code</div>")
return err
})
wrapChildren := templ.ComponentFunc(func(ctx context.Context, w io.Writer) error {
children := templ.GetChildren(ctx)
ctx = templ.ClearChildren(ctx)
_, err := io.WriteString(w, "<div id=\"wrapper\">")
if err != nil {
return err
}
err = children.Render(ctx, w)
if err != nil {
return err
}
_, err = io.WriteString(w, "</div>")
return err
})
note

The templ.ClearChildren function is used to stop passing the children down the tree.

Components as parameters

Components can also be passed as parameters and rendered using the @component expression.

package main

templ heading() {
<h1>Heading</h1>
}

templ layout(contents templ.Component) {
<div id="heading">
@heading()
</div>
<div id="contents">
@contents
</div>
}

templ paragraph(contents string) {
<p>{ contents }</p>
}
main.go
package main

import (
"context"
"os"
)

func main() {
c := paragraph("Dynamic contents")
layout(c).Render(context.Background(), os.Stdout)
}
output
<div id="heading">
<h1>Heading</h1>
</div>
<div id="contents">
<p>Dynamic contents</p>
</div>

You can pass templ components as parameters to other components within templates using standard Go function call syntax.

package main

templ heading() {
<h1>Heading</h1>
}

templ layout(contents templ.Component) {
<div id="heading">
@heading()
</div>
<div id="contents">
@contents
</div>
}

templ paragraph(contents string) {
<p>{ contents }</p>
}

templ root() {
@layout(paragraph("Dynamic contents"))
}
main.go
package main

import (
"context"
"os"
)

func main() {
root().Render(context.Background(), os.Stdout)
}
output
<div id="heading">
<h1>Heading</h1>
</div>
<div id="contents">
<p>Dynamic contents</p>
</div>

Joining Components

Components can be aggregated into a single Component using templ.Join.

package main

templ hello() {
<span>hello</span>
}

templ world() {
<span>world</span>
}

templ helloWorld() {
@templ.Join(hello(), world())
}
main.go
package main

import (
"context"
"os"
)

func main() {
helloWorld().Render(context.Background(), os.Stdout)
}
output
<span>hello</span><span>world</span>

Sharing and re-using components

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.

templ files in the same directory can access each other's components. Components in different directories can be accessed by importing the package that contains the component, so long as the component is exported by capitalizing its name.

tip

In Go, a package is a collection of Go source files in the same directory that are compiled together. All of the functions, types, variables, and constants defined in one source file in a package are available to all other source files in the same package.

Packages exist within a Go module, defined by the go.mod file.

note

Go is structured differently to JavaScript, but uses similar terminology. A single .js or .ts file is like a Go package, and an NPM package is like a Go module.

Exporting components

To make a templ component available to other packages, export it by capitalizing its name.

package components

templ Hello() {
<div>Hello</div>
}

Importing components

To use a component in another package, import the package and use the component as you would any other Go function or type.

package main

import "github.com/a-h/templ/examples/counter/components"

templ Home() {
@components.Hello()
}
tip

To import a component from another Go module, you must first import the module by using the go get <module> command. Then, you can import the component as you would any other Go package.