Contents
This guide moves components from inline core.RenderTemplate strings to
.goui.html files and core.ViewComponent.
Backward compatibility: core.RenderTemplate is not removed. Existing
components keep working. Migration is optional.
When it is worth migrating
Stay on RenderTemplate |
Move to .goui.html |
|---|---|
| Tiny one-liner markup | Multi-section pages / layouts |
| No reuse across components | Shared partials / components / slots |
| Prototype / throwaway demo | Production UI you will edit often |
Step by step
1. Before
func (c *Counter) Render() (string, error) {
return core.RenderTemplate(`<div class="counter">
<span>{{.Count}}</span>
<button g-click="increment">+</button>
</div>`, c)
}
2. Extract the view
Create views/counter.goui.html:
<div class="counter">
<span>{{ .Count }}</span>
<button type="button" g-click="increment">+</button>
</div>
3. Implement View (+ stub Render)
func (c *Counter) View() string { return "counter" }
func (c *Counter) Render() (string, error) {
return "", gouitemplate.ErrViewRenderDirect
}
Go still requires Render on core.Component. template.Wrap intercepts
ViewComponent and never calls the stub.
4. Wire the registries
tmplReg, err := gouitemplate.NewRegistry(gouitemplate.Config{
Root: filepath.Join(exampleDir, "views"),
})
if err != nil {
log.Fatal(err)
}
defer tmplReg.Close()
coreReg := core.NewRegistry()
_ = coreReg.Register("counter", gouitemplate.Wrap(tmplReg, func() core.Component {
return &Counter{}
}))
5. Verify
go buildyour app- Click through events; dirty tracking still uses
MarkDirty/ResetDirty(Wrapclears dirty after a successful view render)
Reference implementation: examples/counter-view
(side by side with unchanged examples/counter).
Checklist
- View file under
Config.Rootwith matching dot-path fromView() - Factory registered with
template.Wrap -
StrictPropsenabled in production if you use@props -
WatchForChangesonly in development