When a child partial is added to a parent partial using the With() method, the parent's data is automatically injected into the child's template context under the .Parent key. This allows child partials to access their parent's data during rendering.
// Create parent partial with data
parentPartial := partial.New("templates/parent.html").ID("parent")
parentPartial.SetData(map[string]any{
"Title": "My List",
"Count": 5,
})
// Create child partial
childPartial := partial.New("templates/child.html").ID("child")
childPartial.SetData(map[string]any{
"ItemName": "Item 1",
})
// Add child to parent
parentPartial.With(childPartial)In the child template, you can access:
.Data- The child's own data.Parent- The parent's data (when rendered as a child).Global- Merged data from all ancestors.Service- Service-level data.Layout- Layout-level data
Parent template (templates/parent.html):
<div class="parent">
<h1>{{ .Data.Title }}</h1>
{{ child "child" }}
</div>Child template (templates/child.html):
<div class="child">
<p>Item: {{ .Data.ItemName }}</p>
<p>From: {{ .Parent.Title }}</p>
<p>Count: {{ .Parent.Count }}</p>
</div>The .Parent field always contains the immediate parent's data, allowing for multi-level hierarchies:
grandparent := partial.New("templates/grandparent.html").ID("grandparent")
grandparent.SetData(map[string]any{"Level": "Grandparent"})
parent := partial.New("templates/parent.html").ID("parent")
parent.SetData(map[string]any{"Level": "Parent"})
child := partial.New("templates/child.html").ID("child")
child.SetData(map[string]any{"Level": "Child"})
parent.With(child)
grandparent.With(parent)Child template:
<div>
My level: {{ .Data.Level }}
Parent level: {{ .Parent.Level }}
<!-- Note: To access grandparent, use .Global which contains merged ancestor data -->
</div>When using the child template function, you can pass additional data that will be merged into the child's .Data:
Parent template:
{{ range .Data.Items }}
{{ child "item" "ItemName" . "Index" $index }}
{{ end }}Child template:
<div>
Item {{ .Data.Index }}: {{ .Data.ItemName }}
From list: {{ .Parent.ListTitle }}
</div>If a partial might be rendered without a parent, you can check if .Parent exists:
<div>
{{ if .Parent }}
Parent: {{ .Parent.Title }}
{{ else }}
No parent
{{ end }}
</div>The complete data structure available in templates:
type Data struct {
Ctx context.Context // Request context
URL *url.URL // Request URL
Request *http.Request // HTTP request
Data map[string]any // This partial's data
Service map[string]any // Service-level data
Layout map[string]any // Layout-level data
Global map[string]any // Merged data from all ancestors
Parent map[string]any // Immediate parent's data
Loc Localizer // Localization helper
Csrf CsrfToken // CSRF token
BasePath string // Base path
}Children can access parent configuration without passing data explicitly:
tablePartial.SetData(map[string]any{
"Columns": []string{"Name", "Age", "Email"},
"Sortable": true,
})In row partials, you can access {{ .Parent.Sortable }} without passing it to each row.
Children can adapt their rendering based on parent context:
{{ if .Parent.CompactMode }}
<div class="compact">{{ .Data.Title }}</div>
{{ else }}
<div class="full">
<h2>{{ .Data.Title }}</h2>
<p>{{ .Data.Description }}</p>
</div>
{{ end }}Parent components can set theme data that children inherit:
containerPartial.SetData(map[string]any{
"Theme": "dark",
"Size": "large",
})Children can then use {{ .Parent.Theme }} and {{ .Parent.Size }} to apply appropriate styles.