Documentation
¶
Overview ¶
Package router provides multi-page routing for tether. It dispatches render and handle calls to the active page based on a field in the session state, enabling single-binary applications with multiple views.
Create a router with a selector function that returns the current page identifier from state, then register pages by path:
r := router.New[State](func(s State) string { return s.Page })
r.Route("/", router.Page[State]{Render: homeRender, Handle: homeHandle})
r.Route("/settings", router.Page[State]{Render: settingsRender, Handle: settingsHandle})
r.NotFound(router.Page[State]{Render: notFoundRender})
Pass r.Render and r.Handle to tether.StatefulConfig:
tether.Stateful(app, tether.StatefulConfig[State]{
Render: r.Render,
Handle: r.Handle,
OnNavigate: r.OnNavigate(func(s *State, p tether.Params) { s.Page = p.Path }),
})
Index ¶
- type Page
- type Router
- func (r *Router[S]) Handle(sess tether.Session, s S, ev tether.Event) S
- func (r *Router[S]) NotFound(page Page[S])
- func (r *Router[S]) OnNavigate(setter func(*S, tether.Params)) func(tether.Session, S, tether.Params) S
- func (r *Router[S]) Render(s S) node.Node
- func (r *Router[S]) Route(path string, page Page[S])
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Page ¶
type Page[S any] struct { Render tether.RenderFunc[S] Handle tether.HandleFunc[S] }
Page defines the render and handle logic for a single route.
type Router ¶
type Router[S any] struct { // contains filtered or unexported fields }
Router manages a set of pages keyed by URL path. It provides tether.HandleFunc and tether.RenderFunc implementations that dispatch to the active page based on a field in the session state.
To use Router, your state must have a field that tracks the current page (typically a string path). Pass a selector function to New that returns this field.
The page registry is stored in an atomic.Value so dispatch (Render and Handle) is completely lock-free. Route and NotFound use a write mutex with copy-on-write semantics.
func New ¶
New creates a router that dispatches based on the string returned by the selector function.
func (*Router[S]) Handle ¶
Handle implements tether.HandleFunc. It dispatches to the active page's Handle function. Lock-free.
func (*Router[S]) NotFound ¶
NotFound sets the page used when the selector returns an unknown path. Thread-safe.
func (*Router[S]) OnNavigate ¶
func (r *Router[S]) OnNavigate(setter func(*S, tether.Params)) func(tether.Session, S, tether.Params) S
OnNavigate is a convenience helper for tether.StatefulConfig.OnNavigate. It wraps a simple setter function in the full OnNavigate signature that StatefulConfig expects (func(Session, S, Params) S), handling the pointer-to-value dance and return plumbing so the caller only writes the state mutation logic. Without this helper, every router user would have to write the same boilerplate closure manually.
The setter receives tether.Params which carries the URL path and query parameters with typed extraction helpers. Params is passed through in full - nothing is discarded - so the setter has access to both the path and every query parameter.
For simple cases where only the path matters:
r.OnNavigate(func(s *State, p tether.Params) { s.Page = p.Path })
For cases that also derive state from query parameters:
r.OnNavigate(func(s *State, p tether.Params) {
s.Page = p.Path
s.Filter = p.Get("f")
s.Limit = p.IntDefault("limit", 20)
})
func (*Router[S]) Render ¶
Render implements tether.RenderFunc. It dispatches to the active page's Render function. Lock-free.