ui

package
v0.601.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 19, 2026 License: MIT Imports: 25 Imported by: 3

README

github.com/linkdata/jaws/lib/ui

This package is the home of JaWS widget implementations.

Goals

  • Keep widget logic out of JaWS core request/session internals.
  • Make new widget authoring local to this package.
  • Provide short widget naming (ui.Span, ui.NewSpan).
  • Expose template context types (ui.RequestWriter, ui.With).
RequestWriter helper calls

ui.RequestWriter exposes helper methods like rw.Span(...), rw.Text(...), and rw.Select(...) for concise template use. rw.Template(tag, ...) renders partial templates inside a generated JaWS wrapper using the provided HTML tag, so template bodies should let that wrapper own JaWS identity and wrapper-level attributes. Passing an empty tag renders the template without a generated wrapper. Attribute params passed to rw.Template(...) are applied to the generated wrapper when one exists. Template bodies used with rw.Template(...) must be partials; full page templates should be rendered through ui.Handler.

Template execution is best-effort rather than transactional. Nested UI helpers such as {{$.Span ...}} register elements as the template runs, and custom template actions may queue updates or mutate application state. If execution later returns an error, JaWS returns or logs that error and preserves whatever already happened; it does not roll back partial output, nested elements, queued messages, or application side effects. On updates, the wrapper's SetInner is queued only after a complete successful render, so a failed update leaves the browser DOM unchanged while earlier server-side side effects from that attempted render may remain. Treat template execution errors as application bugs: validate data before rendering and keep template actions infallible once they start emitting output or nested UI.

You can also use explicit constructors through:

rw.NewUI(ui.NewX(...), params...)

Examples:

rw.NewUI(ui.NewDiv("content"))
rw.NewUI(ui.NewCheckbox(myBoolSetter), "disabled")
rw.NewUI(ui.NewRange(myFloatSetter))

HTML-inner widgets such as NewDiv, NewSpan, and RequestWriter.Div pass their content through bind.MakeHTMLGetter. Plain strings are treated as trusted HTML and are not escaped; use a bind.Getter[string], bind.StringGetterFunc, or fmt.Stringer for string content that should be escaped.

JsVar values are client-writable. If a browser must only write selected fields or bounded collections, make the bound value implement PathSetter and validate allowed paths there. The generic path setter is convenient for trusted demos, but it can write exported JSON fields and append to slices until the serialized MaxClientJsVarBytes cap is hit on render.

Concurrent writes to one JsVar are applied one at a time, and any broadcasts they produce preserve that order. Transport backpressure can delay later writes, but it does not keep the locker passed to NewJsVar held.

Building blocks

  • HTMLInner
    • For tags like <div>...</div>, <span>...</span>, <td>...</td>.
  • Input, InputText, InputBool, InputFloat, InputDate
    • For interactive inputs with typed parse/update behavior.
  • ContainerHelper
    • For widgets that render and maintain dynamic child lists.

Widget lifetime

Every UI widget value is request-scoped. Construct a fresh widget for each request, typically through RequestWriter helpers such as $.Span(...), $.Text(...), $.Container(...), and $.JsVar(...). Do not cache a widget and reuse it across requests, even if that widget currently appears stateless.

The application data referenced by widgets has a separate lifetime. Distinct request-scoped widgets may share synchronized backing state, binders, handlers and tags. For JsVar, use a JsVarMaker when a shared handler or template value needs to create the binding for the current request.

Adding a simple static widget

Embed HTMLInner for the update behavior and render with the exported htmlio.WriteHTMLInner (the package-internal widgets use an equivalent private helper, which is not accessible from outside package ui):

type Article struct{ ui.HTMLInner }

func NewArticle(inner any) *Article {
  return &Article{HTMLInner: ui.HTMLInner{HTMLGetter: bind.MakeHTMLGetter(inner)}}
}

func (w *Article) JawsRender(e *jaws.Element, wr io.Writer, params []any) error {
  _, getterAttrs, err := e.ApplyGetter(w.HTMLGetter)
  if err != nil {
    return err
  }
  attrs := append(e.ApplyParams(params), getterAttrs...)
  return htmlio.WriteHTMLInner(wr, e.Jid(), "article", "", w.HTMLGetter.JawsGetHTML(e), attrs...)
}

// JawsUpdate is inherited from the embedded ui.HTMLInner.

Adding an interactive input widget

Use one of the typed input bases:

  • InputText for string-based inputs
  • InputBool for boolean inputs
  • InputFloat for numeric inputs
  • InputDate for time.Time inputs

Each base handles:

  • tracking last rendered value
  • receiving what.Input
  • applying dirty tags on successful set
  • update-driven SetValue pushes

Adding a container widget

Use ContainerHelper:

type UList struct{ ui.ContainerHelper }

func NewUList(c jaws.Container) *UList {
  return &UList{ContainerHelper: ui.NewContainerHelper(c)}
}

func (w *UList) JawsRender(e *jaws.Element, wr io.Writer, params []any) error {
  return w.RenderContainer(e, wr, "ul", params)
}

func (w *UList) JawsUpdate(e *jaws.Element) {
  w.UpdateContainer(e)
}

Container error behavior

ContainerHelper treats child render/update failures as application bugs.

  • During initial render, child render failures are returned as errors.
  • During updates, append render failures are reported through MustLog (and may panic if no logger is configured).
  • A newly appended child that fails to render is dropped from request state and not appended to the browser DOM, so later updates can retry it from fresh state. Other already-queued update steps are not rolled back.

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:

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

Examples

Constants

This section is empty.

Variables

View Source
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.

View Source
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.

View Source
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.

View Source
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.

View Source
var ErrMissingTemplate errMissingTemplate

ErrMissingTemplate is returned when trying to render an undefined template by name.

View Source
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

func Handler(jw *jaws.Jaws, name string, dot any) http.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

func NewA(innerHTML any) *A

NewA returns an anchor widget whose inner HTML is rendered from innerHTML.

innerHTML is passed to bind.MakeHTMLGetter; plain strings are trusted HTML.

func (*A) JawsRender

func (u *A) JawsRender(elem *jaws.Element, w io.Writer, params []any) error

JawsRender renders ui as an HTML anchor element.

type Button

type Button struct{ HTMLInner }

Button renders an HTML button element with dynamic inner HTML.

func NewButton

func NewButton(innerHTML any) *Button

NewButton returns a button widget whose inner HTML is rendered from innerHTML.

innerHTML is passed to bind.MakeHTMLGetter; plain strings are trusted HTML.

func (*Button) JawsRender

func (u *Button) JawsRender(elem *jaws.Element, w io.Writer, params []any) error

JawsRender renders ui as an HTML button element.

type Checkbox

type Checkbox struct{ InputBool }

Checkbox renders an HTML checkbox input bound to a bool setter.

func NewCheckbox

func NewCheckbox(g bind.Setter[bool]) *Checkbox

NewCheckbox returns a checkbox input widget bound to g.

func (*Checkbox) JawsRender

func (u *Checkbox) JawsRender(elem *jaws.Element, w io.Writer, params []any) error

JawsRender renders ui as an HTML checkbox input.

type Container

type Container struct {
	OuterHTMLTag string
	ContainerHelper
}

Container renders an HTML element around a dynamic child collection.

func NewContainer

func NewContainer(outerHTMLTag string, c jaws.Container) *Container

NewContainer returns a container widget that renders c inside outerHTMLTag. The returned widget tracks child elements and updates them using ContainerHelper.

func (*Container) JawsRender

func (u *Container) JawsRender(elem *jaws.Element, w io.Writer, params []any) error

JawsRender renders ui as its configured container element.

func (*Container) JawsUpdate

func (u *Container) JawsUpdate(elem *jaws.Element)

JawsUpdate updates the child collection.

type ContainerHelper

type ContainerHelper struct {
	Container jaws.Container
	// contains filtered or unexported fields
}

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

func NewDate(g bind.Setter[time.Time]) *Date

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.

func (*Date) JawsRender

func (u *Date) JawsRender(elem *jaws.Element, w io.Writer, params []any) error

JawsRender renders ui as an HTML date input.

type Div

type Div struct{ HTMLInner }

Div renders an HTML div element with dynamic inner HTML.

func NewDiv

func NewDiv(innerHTML any) *Div

NewDiv returns a div widget whose inner HTML is rendered from innerHTML.

innerHTML is passed to bind.MakeHTMLGetter; plain strings are trusted HTML.

func (*Div) JawsRender

func (u *Div) JawsRender(elem *jaws.Element, w io.Writer, params []any) error

JawsRender renders ui as an HTML div element.

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

func (u *HTMLInner) JawsUpdate(elem *jaws.Element)

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

type Img struct{ bind.Getter[string] }

Img renders an HTML img element whose src is read from a string getter.

func NewImg

func NewImg(g bind.Getter[string]) *Img

NewImg returns an img widget whose src attribute is read from g.

func (*Img) JawsRender

func (u *Img) JawsRender(elem *jaws.Element, w io.Writer, params []any) (err error)

JawsRender renders ui as an HTML img element.

func (*Img) JawsUpdate

func (u *Img) JawsUpdate(elem *jaws.Element)

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

type InputBool struct {
	Input
	bind.Setter[bool]
}

InputBool is the reusable base for boolean input widgets.

func (*InputBool) JawsInput added in v0.401.0

func (u *InputBool) JawsInput(elem *jaws.Element, value string) (err error)

JawsInput stores a browser-side bool input value.

func (*InputBool) JawsUpdate

func (u *InputBool) JawsUpdate(elem *jaws.Element)

JawsUpdate updates the input value when the bound bool value changes.

type InputDate

type InputDate struct {
	Input
	bind.Setter[time.Time]
}

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

func (u *InputDate) JawsInput(elem *jaws.Element, value string) (err error)

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

func (u *InputDate) JawsUpdate(elem *jaws.Element)

JawsUpdate updates the input value when the bound date value changes.

type InputFloat

type InputFloat struct {
	Input
	bind.Setter[float64]
}

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

type InputText struct {
	Input
	bind.Setter[string]
}

InputText is the reusable base for string input widgets.

func (*InputText) JawsInput added in v0.401.0

func (u *InputText) JawsInput(elem *jaws.Element, value string) (err error)

JawsInput stores a browser-side string input value.

func (*InputText) JawsUpdate

func (u *InputText) JawsUpdate(elem *jaws.Element)

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

func NewJsVar[T any](l sync.Locker, v *T) *JsVar[T]

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]) JawsGet

func (jsvar *JsVar[T]) JawsGet(elem *jaws.Element) (value T)

JawsGet returns the bound value.

func (*JsVar[T]) JawsGetPath

func (jsvar *JsVar[T]) JawsGetPath(elem *jaws.Element, jsPath string) (value any)

JawsGetPath returns the value at jsPath, logging lookup errors on elem when possible.

func (*JsVar[T]) JawsGetTag

func (jsvar *JsVar[T]) JawsGetTag(tag.Context) any

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

func (jsvar *JsVar[T]) JawsInput(elem *jaws.Element, value string) (err error)

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

func (jsvar *JsVar[T]) JawsRender(elem *jaws.Element, w io.Writer, params []any) (err error)

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

func (jsvar *JsVar[T]) JawsSet(elem *jaws.Element, value T) (err error)

JawsSet replaces the root value and broadcasts the change.

It has the same delivery semantics as JsVar.JawsSetPath.

func (*JsVar[T]) JawsSetPath

func (jsvar *JsVar[T]) JawsSetPath(elem *jaws.Element, jsPath string, value any) (err error)

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

func (jsvar *JsVar[T]) JawsUpdate(elem *jaws.Element)

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

type JsVarMaker interface {
	JawsMakeJsVar(rq *jaws.Request) (value IsJsVar, err error)
}

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

func NewLabel(innerHTML any) *Label

NewLabel returns a label widget whose inner HTML is rendered from innerHTML.

innerHTML is passed to bind.MakeHTMLGetter; plain strings are trusted HTML.

func (*Label) JawsRender

func (u *Label) JawsRender(elem *jaws.Element, w io.Writer, params []any) error

JawsRender renders ui as an HTML label element.

type Li

type Li struct{ HTMLInner }

Li renders an HTML list item with dynamic inner HTML.

func NewLi

func NewLi(innerHTML any) *Li

NewLi returns a list item widget whose inner HTML is rendered from innerHTML.

innerHTML is passed to bind.MakeHTMLGetter; plain strings are trusted HTML.

func (*Li) JawsRender

func (u *Li) JawsRender(elem *jaws.Element, w io.Writer, params []any) error

JawsRender renders ui as an HTML list item.

type Number

type Number struct{ InputFloat }

Number renders an HTML number input bound to a float64 setter.

func NewNumber

func NewNumber(g bind.Setter[float64]) *Number

NewNumber returns a number input widget bound to g.

A non-finite bound value (NaN or ±Inf) renders as a blank control rather than an unparseable value. Contrast NewRange, whose control cannot be blank.

func (*Number) JawsRender

func (u *Number) JawsRender(elem *jaws.Element, w io.Writer, params []any) error

JawsRender renders ui as an HTML number input.

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.

func New added in v0.400.0

func New(innerHTML any) (obj Object)

New returns a new Object that renders innerHTML.

innerHTML is passed to bind.MakeHTMLGetter, which may or may not provide tags. Plain strings are trusted HTML.

type ObjectClickedHook added in v0.500.0

type ObjectClickedHook func(obj Object, elem *jaws.Element, click jaws.Click) (err error)

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

type ObjectContextMenuHook func(obj Object, elem *jaws.Element, click jaws.Click) (err error)

ObjectContextMenuHook is a function to call when a context menu event is received.

type ObjectInitialHTMLAttrHook added in v0.500.0

type ObjectInitialHTMLAttrHook func(obj Object, elem *jaws.Element) (s template.HTMLAttr)

ObjectInitialHTMLAttrHook is a function to call when a jaws.Element is initially rendered.

type Option

type Option struct{ *named.Bool }

Option renders an HTML option element backed by a named.Bool.

func NewOption

func NewOption(nb *named.Bool) Option

NewOption returns an option widget backed by nb.

func (Option) JawsRender

func (u Option) JawsRender(elem *jaws.Element, w io.Writer, params []any) error

JawsRender renders ui as an HTML option element.

func (Option) JawsUpdate

func (u Option) JawsUpdate(elem *jaws.Element)

JawsUpdate updates the selected attribute.

type Password

type Password struct{ InputText }

Password renders an HTML password input bound to a string setter.

func NewPassword

func NewPassword(g bind.Setter[string]) *Password

NewPassword returns a password input widget bound to g.

func (*Password) JawsRender

func (u *Password) JawsRender(elem *jaws.Element, w io.Writer, params []any) error

JawsRender renders ui as an HTML password input.

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.

func NewRadio

func NewRadio(g bind.Setter[bool]) *Radio

NewRadio returns a radio input widget bound to g.

func (*Radio) JawsRender

func (u *Radio) JawsRender(elem *jaws.Element, w io.Writer, params []any) error

JawsRender renders ui as an HTML radio input.

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

func NewRange(g bind.Setter[float64]) *Range

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.

func (*Range) JawsRender

func (u *Range) JawsRender(elem *jaws.Element, w io.Writer, params []any) error

JawsRender renders ui as an HTML range input.

type Register

type Register struct{ jaws.Updater }

Register is an update-only widget that renders no HTML; it exists so its embedded jaws.Updater receives dynamic updates.

func NewRegister

func NewRegister(updater jaws.Updater) Register

NewRegister returns an update-only widget that invokes updater during updates.

func (Register) JawsRender

func (u Register) JawsRender(elem *jaws.Element, w io.Writer, params []any) error

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

type RequestWriter struct {
	*jaws.Request
	io.Writer
}

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) Container

func (rw RequestWriter) Container(outerHTMLTag string, c jaws.Container, params ...any) error

Container renders c inside outerHTMLTag.

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

func (rw RequestWriter) Register(updater jaws.Updater, params ...any) jid.Jid

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

func (u *Select) JawsInput(elem *jaws.Element, value string) (err error)

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

func (u *Select) JawsRender(elem *jaws.Element, w io.Writer, params []any) error

JawsRender renders ui as an HTML select element.

func (*Select) JawsUpdate

func (u *Select) JawsUpdate(elem *jaws.Element)

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

func NewSpan(innerHTML any) *Span

NewSpan returns a span widget whose inner HTML is rendered from innerHTML.

innerHTML is passed to bind.MakeHTMLGetter; plain strings are trusted HTML.

func (*Span) JawsRender

func (u *Span) JawsRender(elem *jaws.Element, w io.Writer, params []any) error

JawsRender renders ui as an HTML span element.

type Tbody

type Tbody struct {
	ContainerHelper
}

Tbody renders an HTML tbody containing dynamic child rows.

func NewTbody

func NewTbody(c jaws.Container) *Tbody

NewTbody returns a tbody widget that renders and updates c as table rows.

func (*Tbody) JawsRender

func (u *Tbody) JawsRender(elem *jaws.Element, w io.Writer, params []any) error

JawsRender renders ui as an HTML tbody element.

func (*Tbody) JawsUpdate

func (u *Tbody) JawsUpdate(elem *jaws.Element)

JawsUpdate updates the child rows.

type Td

type Td struct{ HTMLInner }

Td renders an HTML table cell with dynamic inner HTML.

func NewTd

func NewTd(innerHTML any) *Td

NewTd returns a table cell widget whose inner HTML is rendered from innerHTML.

innerHTML is passed to bind.MakeHTMLGetter; plain strings are trusted HTML.

func (*Td) JawsRender

func (u *Td) JawsRender(elem *jaws.Element, w io.Writer, params []any) error

JawsRender renders ui as an HTML table cell.

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

func NewTemplate(outerHTMLTag, name string, dot any) Template

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

func (tmpl Template) JawsClick(elem *jaws.Element, click jaws.Click) (err error)

JawsClick delegates click events to t.Dot when it implements jaws.ClickHandler.

func (Template) JawsContextMenu added in v0.401.0

func (tmpl Template) JawsContextMenu(elem *jaws.Element, click jaws.Click) (err error)

JawsContextMenu delegates context-menu events to t.Dot when it implements jaws.ContextMenuHandler.

func (Template) JawsInput added in v0.401.0

func (tmpl Template) JawsInput(elem *jaws.Element, value string) (err error)

JawsInput delegates input events to t.Dot when it implements jaws.InputHandler.

func (Template) JawsRender

func (tmpl Template) JawsRender(elem *jaws.Element, w io.Writer, params []any) (err error)

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

func (tmpl Template) JawsUpdate(elem *jaws.Element)

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.

func (Template) String

func (tmpl Template) String() string

String returns a debug representation of t.

type Text

type Text struct{ InputText }

Text renders an HTML text input bound to a string setter.

func NewText

func NewText(g bind.Setter[string]) *Text

NewText returns a text input widget bound to g.

func (*Text) JawsRender

func (u *Text) JawsRender(elem *jaws.Element, w io.Writer, params []any) error

JawsRender renders ui as an HTML text input.

type Textarea

type Textarea struct{ InputText }

Textarea renders an HTML textarea bound to a string setter.

func NewTextarea

func NewTextarea(g bind.Setter[string]) *Textarea

NewTextarea returns a textarea widget bound to g.

func (*Textarea) JawsRender

func (u *Textarea) JawsRender(elem *jaws.Element, w io.Writer, params []any) (err error)

JawsRender renders ui as an HTML textarea.

type Tr

type Tr struct{ HTMLInner }

Tr renders an HTML table row with dynamic inner HTML.

func NewTr

func NewTr(innerHTML any) *Tr

NewTr returns a table row widget whose inner HTML is rendered from innerHTML.

innerHTML is passed to bind.MakeHTMLGetter; plain strings are trusted HTML.

func (*Tr) JawsRender

func (u *Tr) JawsRender(elem *jaws.Element, w io.Writer, params []any) error

JawsRender renders ui as an HTML table row.

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.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL