How to build a multi-root partial
Piko partials do not require a single root element. A <template> with multiple top-level nodes inserts each node at the invocation point. A partial can wrap pre-content, slotted body, and post-content in one file without a synthetic wrapper <div>. For the partial format see pk-file format reference.
Author the multi-root template
<!-- partials/layout.pk -->
<template>
<div>{{ state.Hello }} {{ state.Place }}</div>
<main><piko:slot></piko:slot></main>
<div>{{ state.Goodbye }} {{ state.Place }}</div>
</template>
<script type="application/x-go">
package main
import "piko.sh/piko"
type Props struct {
Place string `prop:"place"`
}
type Response struct {
Hello string
Goodbye string
Place string
}
func Render(r *piko.RequestData, props Props) (Response, piko.Metadata, error) {
return Response{
Hello: "Hello",
Goodbye: "Goodbye",
Place: props.Place,
}, piko.Metadata{}, nil
}
</script>
The template has three top-level nodes. Piko keeps them as siblings. State for the partial - Hello, Goodbye, Place - comes from the partial's own Render function. Callers pass values in via declared props (here, place), not by writing to state.* directly.
Invoke and inspect the output
<piko:partial is="layout" place="world">
<p>Body content</p>
</piko:partial>
Renders as:
<div>Hello world</div>
<main><p>Body content</p></main>
<div>Goodbye world</div>
All three roots land at the call site as siblings. Surrounding markup in the parent template stays unaffected. To pipe a value from the parent's Response, prefix the prop with :server. (or : when the attribute name and prop name match): <piko:partial is="layout" :server.place="state.City">.
Trade-offs
Note: Invocation attributes on a multi-root partial flow to every root, not just the first.
<piko:partial is="layout" class="x">addsxto all three siblings, becauserenderFragmentChildrenpasses the fragment's attributes through to each child element viawriteFragmentAttrs(seeinternal/render/render_domain/orchestrator.goandorchestrator_writers.go). This is good for shared classes anddata-*attributes, but setidon a single-root partial - duplicating anidacross siblings produces invalid HTML.
Piko also stamps each root with internal p-fragment and p-fragment-id attributes so the renderer can correlate the inlined siblings back to the originating partial. These markers appear on the rendered output by design.
A single-root partial gives one DOM element to attach attributes to. Reach for it when the parent needs a unique id, an outer wrapper for ARIA relationships, or a single attachment point for parent CSS scope chains. Reach for a multi-root partial when the partial defines a page region (header + body + footer) where wrapping in an extra <div> would force semantically wrong HTML. Use it only when any invocation attributes you intend to pass make sense on every root.
See also
- PK file format reference for partials and props.
- How to layout partials for the matching layout pattern with slots.
- How to control component attribute merging to predict how invocation attributes combine with each root.