Documentation
¶
Overview ¶
Package ui contains the standard JaWS widget implementations.
The package is intentionally organized around extension-oriented building blocks so new widgets can be authored here without reading JaWS core code:
- HTMLInner: base renderer for tags with inner HTML content.
- Input, InputText, InputBool, InputFloat, InputDate: typed input helpers that handle event/update flow.
- ContainerHelper: helper for widgets that render dynamic child UI lists.
Naming follows short widget names (`Span`, `NewSpan`).
Every widget that implements jaws.UI is request-scoped. Construct a fresh widget for each request, normally by calling a RequestWriter helper while rendering, and never cache a widget for use by multiple requests. Widgets for different requests may refer to the same application state, binders, handlers or tags when that shared state is synchronized as required.
HTML-inner widgets route content through bind.MakeHTMLGetter. Plain strings are treated as trusted HTML, while bind.Getter[string], bind.Binder[string] and fmt.Stringer values are escaped. Raw template.HTMLAttr params are also trusted and written as attributes as-is. Use getter/stringer forms or html/template escaping for untrusted user text.
Index ¶
- Variables
- func Clickable(innerHTML any, onClick func(elem *jaws.Element, click jaws.Click) (err error)) jaws.ClickHandlerdeprecated
- func Handler(jw *jaws.Jaws, name string, dot any) http.Handler
- type A
- type Button
- type Checkbox
- type Container
- type ContainerHelper
- type Date
- type Div
- type HTMLInner
- type Img
- type Input
- type InputBool
- type InputDate
- type InputFloat
- type InputText
- type IsJsVar
- type JsVar
- func (jsvar *JsVar[T]) JawsGet(elem *jaws.Element) (value T)
- func (jsvar *JsVar[T]) JawsGetPath(elem *jaws.Element, jsPath string) (value any)
- func (jsvar *JsVar[T]) JawsGetTag(tag.Context) any
- func (jsvar *JsVar[T]) JawsInput(elem *jaws.Element, value string) (err error)
- func (jsvar *JsVar[T]) JawsRender(elem *jaws.Element, w io.Writer, params []any) (err error)
- func (jsvar *JsVar[T]) JawsSet(elem *jaws.Element, value T) (err error)
- func (jsvar *JsVar[T]) JawsSetPath(elem *jaws.Element, jsPath string, value any) (err error)
- func (jsvar *JsVar[T]) JawsUpdate(elem *jaws.Element)
- type JsVarMaker
- type Label
- type Li
- type Number
- type Object
- type ObjectClickedHook
- type ObjectContextMenuHook
- type ObjectInitialHTMLAttrHook
- type Option
- type Password
- type PathSetter
- type Radio
- type RadioElement
- type Range
- type Register
- type RequestWriter
- func (rw RequestWriter) A(innerHTML any, params ...any) error
- func (rw RequestWriter) Button(innerHTML any, params ...any) error
- func (rw RequestWriter) Checkbox(value any, params ...any) error
- func (rw RequestWriter) Container(outerHTMLTag string, c jaws.Container, params ...any) error
- func (rw RequestWriter) Date(value any, params ...any) error
- func (rw RequestWriter) Div(innerHTML any, params ...any) error
- func (rw RequestWriter) Get(key string) (value any)
- func (rw RequestWriter) HeadHTML() error
- func (rw RequestWriter) Img(imageSrc any, params ...any) error
- func (rw RequestWriter) Initial() *http.Request
- func (rw RequestWriter) JsVar(jsvarName string, jsvar any, params ...any) (err error)
- func (rw RequestWriter) Label(innerHTML any, params ...any) error
- func (rw RequestWriter) Li(innerHTML any, params ...any) error
- func (rw RequestWriter) NewUI(ui jaws.UI, params ...any) (err error)
- func (rw RequestWriter) Number(value any, params ...any) error
- func (rw RequestWriter) Password(value any, params ...any) error
- func (rw RequestWriter) Radio(value any, params ...any) error
- func (rw RequestWriter) RadioGroup(nba *named.BoolArray) (rel []RadioElement)
- func (rw RequestWriter) Range(value any, params ...any) error
- func (rw RequestWriter) Register(updater jaws.Updater, params ...any) jid.Jid
- func (rw RequestWriter) Select(sh named.SelectHandler, params ...any) error
- func (rw RequestWriter) Session() *jaws.Session
- func (rw RequestWriter) Set(key string, value any)
- func (rw RequestWriter) Span(innerHTML any, params ...any) error
- func (rw RequestWriter) TailHTML() error
- func (rw RequestWriter) Tbody(c jaws.Container, params ...any) error
- func (rw RequestWriter) Td(innerHTML any, params ...any) error
- func (rw RequestWriter) Template(outerHTMLTag, name string, dot any, params ...any) error
- func (rw RequestWriter) Text(value any, params ...any) error
- func (rw RequestWriter) Textarea(value any, params ...any) error
- func (rw RequestWriter) Tr(innerHTML any, params ...any) error
- func (rw RequestWriter) Write(p []byte) (n int, err error)
- type Select
- type SetPather
- type Span
- type Tbody
- type Td
- type Template
- func (tmpl Template) JawsClick(elem *jaws.Element, click jaws.Click) (err error)
- func (tmpl Template) JawsContextMenu(elem *jaws.Element, click jaws.Click) (err error)
- func (tmpl Template) JawsInput(elem *jaws.Element, value string) (err error)
- func (tmpl Template) JawsRender(elem *jaws.Element, w io.Writer, params []any) (err error)
- func (tmpl Template) JawsUpdate(elem *jaws.Element)
- func (tmpl Template) String() string
- type Text
- type Textarea
- type Tr
- type With
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var ErrIllegalJsVarName errIllegalJsVarName
ErrIllegalJsVarName is returned when a JsVar name is missing, is not a string, has invalid syntax, or is reserved.
Valid names begin with an ASCII letter, underscore, or dollar sign, and contain only ASCII letters, digits, underscores, and dollar signs. The exact name "__proto__" is reserved.
var ErrIllegalJsVarPath = errors.New("jsvar: path contains illegal protocol byte (tab, newline, carriage return or equals)")
ErrIllegalJsVarPath reports that a JsVar path contained a protocol byte.
A JsVar path is written verbatim into a what.Set frame (only the value side is JSON-encoded), and the client splits frames on '\n', fields on '\t', and the JsVar payload at the first '='. A path carrying those bytes could corrupt the frame, inject fabricated orders, or make peer browsers parse the value as invalid JSON, so JsVar.JawsSetPath rejects it before applying or broadcasting. JsVar.JawsInput applies the same check to the parsed path for incoming browser writes. The raw path is deliberately not echoed in the message to avoid log injection.
var ErrJsVarArgumentType = errors.New("expected jaws.UI or JsVarMaker")
ErrJsVarArgumentType is returned when RequestWriter.JsVar receives an argument that is neither a JaWS UI nor a JsVarMaker.
var ErrJsVarTooLarge = errors.New("jsvar: serialized value exceeds MaxClientJsVarBytes")
ErrJsVarTooLarge reports a failed client-writable JsVar size check.
It aborts the jaws.Request for a JsVar that does not implement PathSetter: JsVar.JawsInput returns it when a boundary confirmation finds the serialized size over the cap or cannot marshal the value, and JsVar.JawsRender returns it when an over-cap value is present at render. See the JsVar SECURITY note.
var ErrMissingTemplate errMissingTemplate
ErrMissingTemplate is returned when trying to render an undefined template by name.
var MaxClientJsVarBytes = 1 << 20 // 1 MiB
MaxClientJsVarBytes bounds the JSON-serialized size of a client-writable JsVar whose bound value does not implement PathSetter.
Without it, a hostile browser could grow such a JsVar's server-side state without bound across many writes (each single write is already bounded by the WebSocket read limit). Raw client-write payload lengths are added to an approximate size; whenever it crosses the cap, json.Marshal confirms the exact size. A confirmed over-cap value or failed confirmation aborts the jaws.Request with ErrJsVarTooLarge; an over-cap value present at render is rejected there instead.
Set it once before serving requests; a value <= 0 disables the cap, and values that implement PathSetter enforce their own bounds and are exempt. It is a plain package global read on the render path, so mutating it while requests are being served is a data race.
Functions ¶
func Clickable
deprecated
added in
v0.304.0
func Clickable(innerHTML any, onClick func(elem *jaws.Element, click jaws.Click) (err error)) jaws.ClickHandler
Clickable returns an object implementing bind.HTMLGetter, jaws.ClickHandler and tag.TagGetter.
innerHTML is passed to bind.MakeHTMLGetter, which may or may not provide tags.
Deprecated: use New(innerHTML).Clicked(...) directly.
func Handler ¶
Handler returns an http.Handler that renders the named template.
The returned handler can be registered directly with a router. Each request results in the template being looked up through the configured template lookupers and rendered with a With value as the template data, exposing dot through its Dot field.
Types ¶
type A ¶
type A struct{ HTMLInner }
An A renders an HTML anchor element with dynamic inner HTML.
func NewA ¶
NewA returns an anchor widget whose inner HTML is rendered from innerHTML.
innerHTML is passed to bind.MakeHTMLGetter; plain strings are trusted HTML.
type Button ¶
type Button struct{ HTMLInner }
Button renders an HTML button element with dynamic inner HTML.
func NewButton ¶
NewButton returns a button widget whose inner HTML is rendered from innerHTML.
innerHTML is passed to bind.MakeHTMLGetter; plain strings are trusted HTML.
type Checkbox ¶
type Checkbox struct{ InputBool }
Checkbox renders an HTML checkbox input bound to a bool setter.
func NewCheckbox ¶
NewCheckbox returns a checkbox input widget bound to g.
type Container ¶
type Container struct {
OuterHTMLTag string
ContainerHelper
}
Container renders an HTML element around a dynamic child collection.
func NewContainer ¶
NewContainer returns a container widget that renders c inside outerHTMLTag. The returned widget tracks child elements and updates them using ContainerHelper.
func (*Container) JawsRender ¶
JawsRender renders ui as its configured container element.
func (*Container) JawsUpdate ¶
JawsUpdate updates the child collection.
type ContainerHelper ¶
ContainerHelper is a helper for widgets that render dynamic child collections.
It tracks already-rendered child elements and performs append/remove/order updates during ContainerHelper.UpdateContainer.
A ContainerHelper belongs to a request-scoped widget instance (for example a widget created via a RequestWriter helper method).
Error model: Child render/update failures are treated as application bugs. Initial-render errors are returned to the caller, and update-time append render errors are reported through MustLog (which may panic when no logger is configured). Update-time child reconciliation is intentionally not transactional: queued browser updates cannot be made atomic, and a rollback path would add hot-path bookkeeping for a user-code render failure without providing a strong correctness guarantee. A newly appended child that fails to render is removed from the request and omitted from the browser append/order batch, so a later update can retry it from fresh state. Treat such failures as application bugs and reload or recover at the application level if needed.
Example (RenderScoped) ¶
package main
import (
"bytes"
"encoding/json"
"fmt"
"github.com/linkdata/jaws"
"github.com/linkdata/jaws/lib/ui"
)
type exampleContainer []string
func (c exampleContainer) JawsContains(elem *jaws.Element) (contents []jaws.UI) {
for _, item := range c {
contents = append(contents, ui.NewSpan(item))
}
return
}
func main() {
first := ui.NewContainer("div", exampleContainer{"one"})
second := ui.NewContainer("div", exampleContainer{"two"})
fmt.Println(first == second)
var b bytes.Buffer
enc := json.NewEncoder(&b)
_ = enc.Encode([]string{"construct containers during render"})
fmt.Print(b.String())
}
Output: false ["construct containers during render"]
func NewContainerHelper ¶
func NewContainerHelper(c jaws.Container) ContainerHelper
NewContainerHelper returns a ContainerHelper for rendering and updating c. ContainerHelper values are request-scoped and must not be reused across requests.
func (*ContainerHelper) RenderContainer ¶
func (u *ContainerHelper) RenderContainer(elem *jaws.Element, w io.Writer, outerHTMLTag string, params []any) (err error)
RenderContainer renders outerHTMLTag around the current children from jaws.Container.JawsContains.
func (*ContainerHelper) UpdateContainer ¶
func (u *ContainerHelper) UpdateContainer(elem *jaws.Element)
UpdateContainer updates child elements to match jaws.Container.JawsContains.
Render errors for newly appended children are reported through jaws.Jaws.MustLog, which may panic when no jaws.Jaws.Logger is configured.
type Date ¶
type Date struct{ InputDate }
Date renders an HTML date input bound to a time value setter.
The control is date-only: a browser edit normalizes the bound time.Time to midnight UTC of the picked date, discarding time-of-day and location. See InputDate.JawsInput.
func NewDate ¶
NewDate returns a date input widget bound to g.
The widget is date-only; see InputDate.JawsInput for how a browser edit normalizes the bound time.Time to midnight UTC.
type Div ¶
type Div struct{ HTMLInner }
Div renders an HTML div element with dynamic inner HTML.
func NewDiv ¶
NewDiv returns a div widget whose inner HTML is rendered from innerHTML.
innerHTML is passed to bind.MakeHTMLGetter; plain strings are trusted HTML.
type HTMLInner ¶
type HTMLInner struct {
// HTMLGetter returns the trusted inner HTML to render and update.
HTMLGetter bind.HTMLGetter
}
HTMLInner is a reusable base for widgets that render as `<tag>inner</tag>`.
func (*HTMLInner) JawsUpdate ¶
JawsUpdate updates the rendered inner HTML.
Unlike the typed input widgets, which dedup against a stored last value, HTMLInner keeps no last-rendered value and re-sends the inner HTML on every update; mark the jaws.Element dirty only when the content has actually changed.
type Img ¶
Img renders an HTML img element whose src is read from a string getter.
func (*Img) JawsRender ¶
JawsRender renders ui as an HTML img element.
func (*Img) JawsUpdate ¶
JawsUpdate updates the src attribute.
Like the other display widgets and unlike the typed inputs, Img keeps no last-rendered value and re-sends src on every update; mark the jaws.Element dirty only when src has actually changed.
type Input ¶
type Input struct {
Last atomic.Value // the last value received from the request
// contains filtered or unexported fields
}
Input stores common state for interactive input widgets. There is one of these per request and input widget.
type InputBool ¶
InputBool is the reusable base for boolean input widgets.
func (*InputBool) JawsUpdate ¶
JawsUpdate updates the input value when the bound bool value changes.
type InputDate ¶
InputDate is the reusable base for date input widgets.
The control is date-only. Rendering shows the calendar date in the bound value's own location, but a browser edit normalizes the bound time.Time to midnight UTC of the picked date; see InputDate.JawsInput.
func (*InputDate) JawsInput ¶ added in v0.401.0
JawsInput stores a browser-side date input value.
The browser sends a calendar date (YYYY-MM-DD), which time.Parse resolves to midnight UTC, so the stored time.Time drops any time-of-day and time.Location the previously bound value carried. In a non-UTC deployment the stored instant therefore shifts by the zone offset, and because time.Time inequality includes the location, re-selecting the same date still reports a change and broadcasts it. Bind a date whose clock and zone are irrelevant, or keep your bound values at midnight UTC to match.
func (*InputDate) JawsUpdate ¶
JawsUpdate updates the input value when the bound date value changes.
type InputFloat ¶
InputFloat is the reusable base for float64 input widgets.
func (*InputFloat) JawsInput ¶ added in v0.401.0
func (u *InputFloat) JawsInput(elem *jaws.Element, value string) (err error)
JawsInput stores a browser-side float64 input value.
func (*InputFloat) JawsUpdate ¶
func (u *InputFloat) JawsUpdate(elem *jaws.Element)
JawsUpdate updates the input value when the bound float64 value changes.
type InputText ¶
InputText is the reusable base for string input widgets.
func (*InputText) JawsUpdate ¶
JawsUpdate updates the input value when the bound string value changes.
type IsJsVar ¶
type IsJsVar interface {
bind.RWLocker
jaws.UI
jaws.InputHandler
PathSetter
}
IsJsVar is implemented by JaWS UI values that bind a Go value to a browser-side JavaScript variable.
type JsVar ¶
type JsVar[T any] struct { bind.RWLocker Ptr *T // bound Go value // contains filtered or unexported fields }
JsVar binds a Go value to a named JavaScript variable in the browser.
A JsVar is request-scoped and must not be rendered by more than one jaws.Request. Construct a fresh JsVar for each request, either directly while rendering or through JsVarMaker. Distinct JsVar values may use the same locker and Ptr to expose synchronized application state to multiple requests.
JsVar is intended for JSON-marshalable state shared with application JavaScript. The browser binding reads and writes the window property named when the JsVar is rendered. Existing application variables are therefore valid bindings. Do not use a browser-owned property such as window.name, or a global owned by unrelated code.
Multiple bindings may share a name. The name is a single browser window property, and a browser-initiated write to it is delivered to every live binding of that name; a removed binding stops receiving writes. This lets a subtree re-render replace a binding, lets several requests expose the same application-owned global, and lets one browser value fan out to several independent Go bindings.
When bindings sharing a name also share backing state (the same locker and Ptr), a browser write applies to that shared value once per binding. Do not expose one Ptr through several simultaneously rendered bindings when its PathSetter is not idempotent (for example one that appends).
Unlike most JaWS UI values, a JsVar is a bidirectional channel and does not imply that the Go value is always authoritative. Browser and Go updates may each carry a complete value or individual paths. Any desired ownership, conflict, or merge policy is the application's responsibility.
When Ptr is non-nil, JsVar.JawsRender serializes a snapshot of the bound Go value to initialize the browser variable. A browser call to the JavaScript jawsVar function sends only while its WebSocket is open; an earlier call is not queued for later transmission. JsVar.JawsSet and JsVar.JawsSetPath broadcast only to matching active requests, so an update is not replayed to a page between its initial render and its broadcast subscription. Applications that require the two sides to converge after either can change the value during that interval must reconcile it explicitly.
It is safe for concurrent use when the locker passed to NewJsVar is safe for concurrent use. Concurrent writes are applied one at a time. Any broadcasts they produce preserve the order in which the writes modify the bound value. This concurrency guarantee does not permit one JsVar to be shared between requests.
A JsVar must not be copied after first use.
SECURITY: a JsVar is client-writable. Incoming browser "set" messages are applied by path to the bound value. If the bound value implements PathSetter its JawsSetPath validates and applies the change; otherwise the change is applied by the generic path setter (github.com/linkdata/jq.Set), which will set any exported field — matched by its json tag, or by the Go field name when it has no json tag (a json:"-" tag is never writable) — and append to slices one element per message. The size of any single client write is bounded by the WebSocket read limit; to also stop a hostile client growing server state without bound across many writes, a non-PathSetter value accumulates raw client-write payload lengths as an approximate size. When the approximation crosses MaxClientJsVarBytes, json.Marshal measures the exact serialized size. An over-cap value or failed measurement aborts the jaws.Request with ErrJsVarTooLarge (an over-cap value present at render is likewise rejected). The cap does not prevent a client from setting individual exported fields, so when only some fields/paths should be client-writable, implement PathSetter on the bound value to allow-list paths and bound lengths. See the Node type in github.com/linkdata/jawstree for an example that restricts client writes to a single boolean field.
Example (PathSetter) ¶
package main
import (
"errors"
"fmt"
"sync"
"github.com/linkdata/jaws"
"github.com/linkdata/jaws/lib/ui"
)
type examplePathState struct {
Title string `json:"title"`
Items []string `json:"items"`
}
func (state *examplePathState) JawsSetPath(elem *jaws.Element, jsPath string, value any) error {
if jsPath != "title" {
return fmt.Errorf("%w: %s", ui.ErrIllegalJsVarPath, jsPath)
}
title, ok := value.(string)
if !ok {
return fmt.Errorf("title: %T", value)
}
if state.Title == title {
return jaws.ErrValueUnchanged
}
state.Title = title
return nil
}
func main() {
var mu sync.Mutex
state := examplePathState{Title: "old", Items: []string{"server-owned"}}
jsv := ui.NewJsVar(&mu, &state)
if err := jsv.JawsSetPath(nil, "title", "new"); err != nil {
panic(err)
}
err := jsv.JawsSetPath(nil, "items.1", "blocked")
fmt.Println(state.Title)
fmt.Println(errors.Is(err, ui.ErrIllegalJsVarPath))
}
Output: new true
func NewJsVar ¶
NewJsVar creates a JsVar over v protected by l.
The locker l must be non-nil and must remain valid for the lifetime of the JsVar. Create a fresh JsVar for each request; l and v may be shared by distinct request-scoped JsVar values. Use JsVarMaker when construction depends on the current request or the maker is stored in shared handler data.
func (*JsVar[T]) JawsGetPath ¶
JawsGetPath returns the value at jsPath, logging lookup errors on elem when possible.
func (*JsVar[T]) JawsGetTag ¶
JawsGetTag returns the current dirty tag.
It is safe for concurrent use. The tag.Context argument is ignored and may be nil.
func (*JsVar[T]) JawsInput ¶ added in v0.401.0
JawsInput applies a browser-side JavaScript variable update.
A single incoming message is already bounded by the connection's WebSocket read limit (SetReadLimit in the request handler). To also bound cumulative growth, a non-PathSetter value is size-accounted after each browser write — including a write the bound value rejects, because github.com/linkdata/jq.Set grows a slice before assigning the appended element, so even a rejected append enlarges server state. The request is aborted with ErrJsVarTooLarge on the first write whose confirmed serialized size passes MaxClientJsVarBytes. Accounting adds the raw client-write payload length to an approximate running size and marshals the whole value only when that approximation crosses the cap, so an append flood stays O(n) rather than O(n^2). A marshaling error during confirmation also aborts the request and returns ErrJsVarTooLarge, with the marshal error retained as its cancellation cause.
func (*JsVar[T]) JawsRender ¶
JawsRender writes the hidden element that seeds and routes the JavaScript variable.
params[0] must be a valid JsVar name. Otherwise, JawsRender returns ErrIllegalJsVarName without writing markup.
A name may be bound by more than one live binding; see JsVar for how a browser write is delivered to every live binding of the name.
The serialized value is a render-time snapshot. See JsVar for the synchronization semantics between rendering and the WebSocket subscription.
The bound value's tag.TagGetter.JawsGetTag and jaws.InitHandler.JawsInit callbacks run while the JsVar write lock is held, so they must not re-enter this JsVar (for example call JawsGet or JawsSet on it), which would self-deadlock the non-reentrant lock.
func (*JsVar[T]) JawsSet ¶
JawsSet replaces the root value and broadcasts the change.
It has the same delivery semantics as JsVar.JawsSetPath.
func (*JsVar[T]) JawsSetPath ¶
JawsSetPath sets the value at jsPath and broadcasts the change when possible. It is a programmatic (server-side, trusted) write and is not size-capped at the write boundary; see MaxClientJsVarBytes for the browser-write cap.
A nil elem changes the bound value without broadcasting. A set before this JsVar has acquired a dirty tag from rendering also produces no broadcast; its initial render seeds the value via the data-jawsdata attribute.
The broadcast reaches matching active requests only. It is not replayed to a page between its initial render and its broadcast subscription; see JsVar for the synchronization model.
func (*JsVar[T]) JawsUpdate ¶
JawsUpdate is a no-op because updates are broadcast by path setters.
Dirtying a JsVar therefore does not resend its root value. Use JsVar.JawsSet or JsVar.JawsSetPath, together with the application's synchronization policy, to send changes.
type JsVarMaker ¶
JsVarMaker creates a request-scoped JavaScript variable binding.
JawsMakeJsVar must return a fresh IsJsVar for each request. The returned bindings may share synchronized backing state, but the bindings themselves must not be shared between requests.
type Label ¶
type Label struct{ HTMLInner }
Label renders an HTML label element with dynamic inner HTML.
func NewLabel ¶
NewLabel returns a label widget whose inner HTML is rendered from innerHTML.
innerHTML is passed to bind.MakeHTMLGetter; plain strings are trusted HTML.
type Li ¶
type Li struct{ HTMLInner }
Li renders an HTML list item with dynamic inner HTML.
func NewLi ¶
NewLi returns a list item widget whose inner HTML is rendered from innerHTML.
innerHTML is passed to bind.MakeHTMLGetter; plain strings are trusted HTML.
type Number ¶
type Number struct{ InputFloat }
Number renders an HTML number input bound to a float64 setter.
type Object ¶ added in v0.400.0
type Object interface {
bind.HTMLGetter
tag.TagGetter
jaws.ClickHandler
jaws.ContextMenuHandler
jaws.InitialHTMLAttrHandler
// Clicked returns an [Object] that will call fn when [jaws.ClickHandler.JawsClick] is invoked.
Clicked(fn ObjectClickedHook) (newobj Object)
// ContextMenu returns an [Object] that will call fn when
// [jaws.ContextMenuHandler.JawsContextMenu] is invoked.
ContextMenu(fn ObjectContextMenuHook) (newobj Object)
// InitialHTMLAttr returns an [Object] that will call fn when
// [jaws.InitialHTMLAttrHandler.JawsInitialHTMLAttr] is invoked.
InitialHTMLAttr(fn ObjectInitialHTMLAttrHook) (newobj Object)
}
Object is a chainable UI object that combines HTML rendering, tags and optional event handlers.
type ObjectClickedHook ¶ added in v0.500.0
ObjectClickedHook is a function to call when a click event is received.
It is named distinctly from the generic bind.ClickedHook to avoid confusion: this one operates on an Object, not a bind.Binder.
type ObjectContextMenuHook ¶ added in v0.500.0
ObjectContextMenuHook is a function to call when a context menu event is received.
type ObjectInitialHTMLAttrHook ¶ added in v0.500.0
ObjectInitialHTMLAttrHook is a function to call when a jaws.Element is initially rendered.
type Option ¶
Option renders an HTML option element backed by a named.Bool.
func (Option) JawsRender ¶
JawsRender renders ui as an HTML option element.
func (Option) JawsUpdate ¶
JawsUpdate updates the selected attribute.
type Password ¶
type Password struct{ InputText }
Password renders an HTML password input bound to a string setter.
func NewPassword ¶
NewPassword returns a password input widget bound to g.
type PathSetter ¶
type PathSetter interface {
// JawsSetPath should set the JSON object member identified by jsPath to the given value.
//
// If the member is already the given value, it should return [jaws.ErrValueUnchanged].
//
// When a [JsVar]'s bound value (Ptr) implements PathSetter, the JsVar
// delegates to it while holding the JsVar write lock. Such an
// implementation must not lock or unlock the JsVar, nor call its locked
// accessors such as [JsVar.JawsGet] or [JsVar.JawsSet].
//
// If an implementation panics, the calling JsVar releases its write lock
// before propagating the panic.
JawsSetPath(elem *jaws.Element, jsPath string, value any) (err error)
}
PathSetter can set a nested JSON path value.
type Radio ¶
type Radio struct{ InputBool }
Radio renders an HTML radio input bound to a bool setter.
type RadioElement ¶
type RadioElement struct {
// contains filtered or unexported fields
}
RadioElement renders the input and label elements for one radio option.
The underlying jaws.Element values are created lazily on the first call to RadioElement.Radio or RadioElement.Label, so options that a template never renders register no elements on the jaws.Request. Call each of Radio and Label at most once. Render Label only when Radio is also rendered: Label emits a for="..." referencing the radio's id, so a Label without its Radio points at an input that is absent from the document (and leaves an unrendered radio Element registered on the Request for the request's lifetime).
func (RadioElement) Label ¶
func (re RadioElement) Label(params ...any) template.HTML
Label renders an HTML label element.
The generated for= attribute referencing the radio's id takes precedence over any for= passed in params: it is emitted first and the HTML parser keeps the first of duplicate attributes, so the label always targets its own radio.
Render errors are reported through jaws.Jaws.MustLog, which panics when no jaws.Jaws.Logger is configured.
func (RadioElement) Radio ¶
func (re RadioElement) Radio(params ...any) template.HTML
Radio renders an HTML input element of type radio.
The group's generated name= attribute takes precedence over any name= passed in params: it is emitted first and the HTML parser keeps the first of duplicate attributes, preserving the invariant that every radio in the group shares the same request-scoped name.
Render errors are reported through jaws.Jaws.MustLog, which panics when no jaws.Jaws.Logger is configured.
type Range ¶
type Range struct{ InputFloat }
Range renders an HTML range input bound to a float64 setter.
func NewRange ¶
NewRange returns a range input widget bound to g.
A range control cannot display a non-finite value: a bound NaN or ±Inf shows as the browser's constraint-sanitized default value for the control, not a blank field, while the bound value stays non-finite. Use NewNumber if the bound value may be non-finite.
type Register ¶
Register is an update-only widget that renders no HTML; it exists so its embedded jaws.Updater receives dynamic updates.
func NewRegister ¶
NewRegister returns an update-only widget that invokes updater during updates.
func (Register) JawsRender ¶
JawsRender renders no HTML for update-only registration.
It ignores params; to attach extra tags or event handlers, use RequestWriter.Register, which applies them before the element is frozen.
type RequestWriter ¶
RequestWriter combines a jaws.Request with an io.Writer while rendering.
func (RequestWriter) A ¶
func (rw RequestWriter) A(innerHTML any, params ...any) error
A renders an HTML anchor element. A plain string innerHTML is trusted HTML; see NewA and bind.MakeHTMLGetter to pass untrusted input safely.
func (RequestWriter) Button ¶
func (rw RequestWriter) Button(innerHTML any, params ...any) error
Button renders an HTML button element. A plain string innerHTML is trusted HTML; see NewButton and bind.MakeHTMLGetter to pass untrusted input safely.
func (RequestWriter) Checkbox ¶
func (rw RequestWriter) Checkbox(value any, params ...any) error
Checkbox renders an HTML checkbox input.
func (RequestWriter) Date ¶
func (rw RequestWriter) Date(value any, params ...any) error
Date renders an HTML date input.
The control is date-only: a browser edit normalizes the bound time.Time to midnight UTC of the picked date, discarding time-of-day and location. See InputDate.JawsInput.
func (RequestWriter) Div ¶
func (rw RequestWriter) Div(innerHTML any, params ...any) error
Div renders an HTML div element. A plain string innerHTML is trusted HTML; see NewDiv and bind.MakeHTMLGetter to pass untrusted input safely.
func (RequestWriter) Get ¶
func (rw RequestWriter) Get(key string) (value any)
Get calls jaws.Request.Get.
func (RequestWriter) HeadHTML ¶
func (rw RequestWriter) HeadHTML() error
HeadHTML calls jaws.Request.HeadHTML.
func (RequestWriter) Img ¶
func (rw RequestWriter) Img(imageSrc any, params ...any) error
Img renders an HTML img element.
func (RequestWriter) Initial ¶
func (rw RequestWriter) Initial() *http.Request
Initial returns the initial http.Request.
func (RequestWriter) JsVar ¶
func (rw RequestWriter) JsVar(jsvarName string, jsvar any, params ...any) (err error)
JsVar binds a JsVar to a named JavaScript variable.
jsvarName identifies a property on the browser window. It should be owned by the application because the binding initializes and updates its value.
See JsVar for the bidirectional binding and synchronization semantics, including how a name shared by several live bindings is routed.
It returns ErrIllegalJsVarName if jsvarName is invalid or reserved.
A directly supplied JsVar must be scoped to rw.Request. You can instead pass a JsVarMaker, which is useful when the maker is stored in handler or template data shared by multiple requests.
func (RequestWriter) Label ¶
func (rw RequestWriter) Label(innerHTML any, params ...any) error
Label renders an HTML label element. A plain string innerHTML is trusted HTML; see NewLabel and bind.MakeHTMLGetter to pass untrusted input safely.
func (RequestWriter) Li ¶
func (rw RequestWriter) Li(innerHTML any, params ...any) error
Li renders an HTML list item. A plain string innerHTML is trusted HTML; see NewLi and bind.MakeHTMLGetter to pass untrusted input safely.
func (RequestWriter) NewUI ¶ added in v0.500.0
func (rw RequestWriter) NewUI(ui jaws.UI, params ...any) (err error)
NewUI creates an element for ui and renders it to the underlying writer.
func (RequestWriter) Number ¶
func (rw RequestWriter) Number(value any, params ...any) error
Number renders an HTML number input.
See NewNumber for how a non-finite bound value renders.
func (RequestWriter) Password ¶
func (rw RequestWriter) Password(value any, params ...any) error
Password renders an HTML password input.
func (RequestWriter) Radio ¶
func (rw RequestWriter) Radio(value any, params ...any) error
Radio renders an HTML radio input.
func (RequestWriter) RadioGroup ¶
func (rw RequestWriter) RadioGroup(nba *named.BoolArray) (rel []RadioElement)
RadioGroup returns a RadioElement for each value in nba.
Elements are created lazily as they are rendered; see RadioElement. Every rendered radio in the group shares a name derived from the first created radio Element's request-scoped jaws.Jid.
func (RequestWriter) Range ¶
func (rw RequestWriter) Range(value any, params ...any) error
Range renders an HTML range input.
See NewRange for how a non-finite bound value renders.
func (RequestWriter) Register ¶
Register creates a new Element with the given Updater as a tag for dynamic updates. Additional tags may be provided in params. If updater also implements an event handler interface, it receives matching events after handlers provided in params have had a chance to handle them. The updater's jaws.Updater.JawsUpdate method will be called immediately to ensure the initial rendering is correct.
Register does not call jaws.Renderer.JawsRender. The updater must therefore be ready for JawsUpdate and event handling without render-time initialization. In particular, the standard input widgets and Select initialize their dirty targets while rendering; register them with RequestWriter.NewUI or their RequestWriter helper when they need to handle input events.
Returns a jid.Jid, suitable for including as an HTML id attribute:
<div id="{{$.Register .MyUpdater}}">...</div>
func (RequestWriter) Select ¶
func (rw RequestWriter) Select(sh named.SelectHandler, params ...any) error
Select renders a single-selection HTML select element.
Params are rendered as supplied. Passing a multiple attribute is unsupported because the widget stores one selected option name.
func (RequestWriter) Session ¶
func (rw RequestWriter) Session() *jaws.Session
Session returns the request's jaws.Session, or nil.
func (RequestWriter) Set ¶
func (rw RequestWriter) Set(key string, value any)
Set calls jaws.Request.Set.
func (RequestWriter) Span ¶
func (rw RequestWriter) Span(innerHTML any, params ...any) error
Span renders an HTML span element. A plain string innerHTML is trusted HTML; see NewSpan and bind.MakeHTMLGetter to pass untrusted input safely.
func (RequestWriter) TailHTML ¶
func (rw RequestWriter) TailHTML() error
TailHTML writes optional HTML code at the end of the page's BODY section that will immediately apply updates made during initial rendering.
func (RequestWriter) Tbody ¶
func (rw RequestWriter) Tbody(c jaws.Container, params ...any) error
Tbody renders an HTML tbody element.
func (RequestWriter) Td ¶
func (rw RequestWriter) Td(innerHTML any, params ...any) error
Td renders an HTML table cell. A plain string innerHTML is trusted HTML; see NewTd and bind.MakeHTMLGetter to pass untrusted input safely.
func (RequestWriter) Template ¶
func (rw RequestWriter) Template(outerHTMLTag, name string, dot any, params ...any) error
Template renders the named partial template with dot exposed as With.Dot, wrapping the output in a generated outerHTMLTag element (unwrapped if empty) that owns the JaWS ID and any HTML attrs in params. See NewTemplate and Template.
func (RequestWriter) Text ¶
func (rw RequestWriter) Text(value any, params ...any) error
Text renders an HTML text input.
func (RequestWriter) Textarea ¶
func (rw RequestWriter) Textarea(value any, params ...any) error
Textarea renders an HTML textarea.
func (RequestWriter) Tr ¶
func (rw RequestWriter) Tr(innerHTML any, params ...any) error
Tr renders an HTML table row. A plain string innerHTML is trusted HTML; see NewTr and bind.MakeHTMLGetter to pass untrusted input safely.
func (RequestWriter) Write ¶
func (rw RequestWriter) Write(p []byte) (n int, err error)
Write records the write instant (see jaws.Request.MarkWritten), then writes p to the underlying writer.
type Select ¶
type Select struct {
ContainerHelper
}
Select renders a single-selection HTML select element.
The widget stores one selected option name through a named.SelectHandler. Render params are written as supplied, but a multiple select is not supported by the JaWS select value contract.
func NewSelect ¶
func NewSelect(sh named.SelectHandler) *Select
NewSelect returns a single-selection select widget backed by sh.
The widget reads and writes one selected option name through sh.
func (*Select) JawsInput ¶ added in v0.401.0
JawsInput stores one browser-side selected option name.
The input is ignored (returning a nil error) when the Container is not a bind.Setter of string.
func (*Select) JawsRender ¶
JawsRender renders ui as an HTML select element.
func (*Select) JawsUpdate ¶
JawsUpdate updates the selected value and child options.
Unlike the typed inputs, it re-sends the select value on every update with no dedup against a last value, so mark the element dirty only when the value or options actually changed.
type SetPather ¶
type SetPather interface {
// JawsPathSet notifies that a JSON object member identified by jsPath has been set
// to the given value and the change has been queued for broadcast.
//
// Unlike [PathSetter.JawsSetPath], a [JsVar] calls this after releasing
// its lock, so locking the JsVar or calling its locked accessors is
// allowed here.
JawsPathSet(elem *jaws.Element, jsPath string, value any)
}
SetPather is notified after a nested JSON path value has been set and broadcast.
type Span ¶
type Span struct{ HTMLInner }
Span renders an HTML span element with dynamic inner HTML.
func NewSpan ¶
NewSpan returns a span widget whose inner HTML is rendered from innerHTML.
innerHTML is passed to bind.MakeHTMLGetter; plain strings are trusted HTML.
type Tbody ¶
type Tbody struct {
ContainerHelper
}
Tbody renders an HTML tbody containing dynamic child rows.
func (*Tbody) JawsRender ¶
JawsRender renders ui as an HTML tbody element.
func (*Tbody) JawsUpdate ¶
JawsUpdate updates the child rows.
type Td ¶
type Td struct{ HTMLInner }
Td renders an HTML table cell with dynamic inner HTML.
func NewTd ¶
NewTd returns a table cell widget whose inner HTML is rendered from innerHTML.
innerHTML is passed to bind.MakeHTMLGetter; plain strings are trusted HTML.
type Template ¶
type Template struct {
OuterHTMLTag string // Optional wrapper tag for partial templates, for example "div" or "tr"; empty renders unwrapped.
Name string // Template name to be looked up using Jaws.LookupTemplate.
Dot any // Dot value to place in With.
}
Template references a Go html/template template to be rendered through JaWS.
The OuterHTMLTag field identifies the generated wrapper element used for partial templates. If OuterHTMLTag is empty, the template is rendered without a generated wrapper. Name identifies the template to execute and Dot contains the data exposed to the template through the With structure constructed during rendering. Wrapped templates receive the JaWS ID and any HTML attributes supplied at render time through the RequestWriter.Template helper. The referenced template must be a partial template, not a full HTML document.
Template execution is best-effort rather than transactional. Template actions and nested JaWS helpers run as the template executes, so an execution error after partial output can leave already-written HTML, registered nested elements, queued messages, domain mutations or other side effects in place. Treat such errors as application bugs: validate data before rendering and keep template actions infallible once they start emitting output or nested UI.
Example (FailureBehavior) ¶
package main
import (
"bytes"
"fmt"
"html/template"
"strings"
"github.com/linkdata/jaws"
"github.com/linkdata/jaws/lib/tag"
"github.com/linkdata/jaws/lib/ui"
)
func main() {
tmpl := template.Must(template.New("partial").Parse(`before {{.Dot}} {{call .Missing}} after`))
jw, err := jaws.New()
if err != nil {
panic(err)
}
defer jw.Close()
if err = jw.AddTemplateLookuper(tmpl); err != nil {
panic(err)
}
rq := jw.NewRequest(nil)
elem := rq.NewElement(ui.NewTemplate("div", "partial", tag.Tag("dot")))
var out bytes.Buffer
err = elem.JawsRender(&out, nil)
fmt.Println(strings.Contains(out.String(), `id="Jid.1"`))
fmt.Println(strings.Contains(out.String(), "before dot"))
fmt.Println(err != nil)
}
Output: true true true
func NewTemplate ¶
NewTemplate returns a Template for rendering the named partial template with dot exposed as With.Dot.
outerHTMLTag names the generated wrapper element that owns the JaWS ID and render-time HTML attributes, or renders unwrapped (and Template.JawsUpdate has no wrapper to update) if empty. The name is resolved at render or update time via jaws.Jaws.LookupTemplate. See Template for the field semantics, event delegation and best-effort error behavior.
func (Template) JawsClick ¶ added in v0.401.0
JawsClick delegates click events to t.Dot when it implements jaws.ClickHandler.
func (Template) JawsContextMenu ¶ added in v0.401.0
JawsContextMenu delegates context-menu events to t.Dot when it implements jaws.ContextMenuHandler.
func (Template) JawsInput ¶ added in v0.401.0
JawsInput delegates input events to t.Dot when it implements jaws.InputHandler.
func (Template) JawsRender ¶
JawsRender renders t through the request's configured template lookupers, streaming output directly to w. Template execution has the best-effort error behavior described on Template.
func (Template) JawsUpdate ¶
JawsUpdate re-renders t into the template wrapper.
Unwrapped templates have no generated DOM element to update, so updates are ignored; nested JaWS UI rendered by the template can still update through its own elements. The wrapper's SetInner is queued only after execution succeeds (see the best-effort error behavior on Template).
Lookup or execution errors are reported through jaws.Request.MustLog, which may panic when no jaws.Jaws.Logger is configured.
type Text ¶
type Text struct{ InputText }
Text renders an HTML text input bound to a string setter.
type Textarea ¶
type Textarea struct{ InputText }
Textarea renders an HTML textarea bound to a string setter.
func NewTextarea ¶
NewTextarea returns a textarea widget bound to g.
type Tr ¶
type Tr struct{ HTMLInner }
Tr renders an HTML table row with dynamic inner HTML.
func NewTr ¶
NewTr returns a table row widget whose inner HTML is rendered from innerHTML.
innerHTML is passed to bind.MakeHTMLGetter; plain strings are trusted HTML.
type With ¶
type With struct {
*jaws.Element // the Element being rendered using a template
RequestWriter // the RequestWriter for nested UI helpers
Dot any // user data parameter
// Auth is the authentication information from [jaws.Jaws.MakeAuth]. When
// MakeAuth is nil it is a [jaws.DefaultAuth], whose IsAdmin returns true for
// everyone — gating UI on {{if .Auth.IsAdmin}} is only safe once MakeAuth is
// set. See [jaws.DefaultAuth] for the fail-open caveat.
Auth jaws.Auth
}
With is passed as the data parameter when using RequestWriter.Template, populated with all required members set.
Source Files
¶
- a.go
- button.go
- checkbox.go
- clickable.go
- common.go
- container.go
- containerhelper.go
- date.go
- div.go
- doc.go
- errjsvar.go
- errmissingtemplate.go
- handler.go
- html_widgets.go
- img.go
- input_widgets.go
- jsvar.go
- label.go
- li.go
- number.go
- object.go
- option.go
- password.go
- radio.go
- radiogroup.go
- range.go
- register.go
- requestwriter.go
- select.go
- span.go
- tbody.go
- td.go
- template.go
- text.go
- textarea.go
- tr.go
- with.go