ui

package
v0.400.0 Latest Latest
Warning

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

Go to latest
Published: Apr 15, 2026 License: MIT Imports: 28 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.

You can also use explicit constructors through:

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

Examples:

rw.UI(ui.NewDiv(bind.MakeHTMLGetter("content")))
rw.UI(ui.NewCheckbox(myBoolSetter), "disabled")
rw.UI(ui.NewRange(myFloatSetter))

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

UI widget values are render-scoped. Construct them during rendering, typically through RequestWriter helpers such as $.Container(...) and $.Tbody(...).

Do not cache and reuse *ui.Container / *ui.Tbody instances across requests. Those widgets keep internal render/update bookkeeping and are intended to be created fresh for each render.

Adding a simple static widget

Use HTMLInner:

type Article struct{ ui.HTMLInner }

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

func (w *Article) JawsRender(e *jaws.Element, wr io.Writer, params []any) error {
  return w.renderInner(e, wr, "article", "", params)
}

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).
  • After such failures, partial DOM/request state updates are expected; state may remain inconsistent until a subsequent full render/reload.

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`) instead of the legacy core names (`UiSpan`, `NewUiSpan`).

Index

Constants

This section is empty.

Variables

View Source
var ErrIllegalJsVarName errIllegalJsVarName

ErrIllegalJsVarName is returned when a JsVar name is missing, not a string, or does not follow valid top-level identifier syntax.

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 ErrMissingTemplate errMissingTemplate

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

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 jaws.TagGetter. innerHTML is passed to 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 dot as the template data.

Types

type A

type A struct{ HTMLInner }

func NewA

func NewA(innerHTML bind.HTMLGetter) *A

func (*A) JawsRender

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

type Button

type Button struct{ HTMLInner }

func NewButton

func NewButton(innerHTML bind.HTMLGetter) *Button

func (*Button) JawsRender

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

type Checkbox

type Checkbox struct{ InputBool }

func NewCheckbox

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

func (*Checkbox) JawsRender

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

type ClickedHook added in v0.400.0

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

ClickedHook is a function to call when a click event is received.

type Container

type Container struct {
	OuterHTMLTag string
	ContainerHelper
}

func NewContainer

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

func (*Container) JawsRender

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

func (*Container) JawsUpdate

func (ui *Container) JawsUpdate(e *jaws.Element)

type ContainerHelper

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

ContainerHelper is a helper for widgets that render dynamic child collections.

It tracks previously rendered child elements and performs append/remove/order updates during JawsUpdate.

A ContainerHelper belongs to a widget instance and is intended for render-scoped widget lifetimes (for example widgets created via RequestWriter helper methods).

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). After such failures, DOM and request-tracked element state may be partially updated and therefore inconsistent until the next full render/reload.

func NewContainerHelper

func NewContainerHelper(c jaws.Container) ContainerHelper

func (*ContainerHelper) RenderContainer

func (ui *ContainerHelper) RenderContainer(e *jaws.Element, w io.Writer, outerHTMLTag string, params []any) (err error)

func (*ContainerHelper) UpdateContainer

func (ui *ContainerHelper) UpdateContainer(e *jaws.Element)

type ContextMenuHook added in v0.400.0

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

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

type Date

type Date struct{ InputDate }

func NewDate

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

func (*Date) JawsRender

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

type Div

type Div struct{ HTMLInner }

func NewDiv

func NewDiv(innerHTML bind.HTMLGetter) *Div

func (*Div) JawsRender

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

type HTMLInner

type HTMLInner struct {
	HTMLGetter bind.HTMLGetter
}

HTMLInner is a reusable base for widgets that render as `<tag>inner</tag>`.

func (*HTMLInner) JawsUpdate

func (ui *HTMLInner) JawsUpdate(e *jaws.Element)

type Img

type Img struct{ bind.Getter[string] }

func NewImg

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

func (*Img) JawsRender

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

func (*Img) JawsUpdate

func (ui *Img) JawsUpdate(e *jaws.Element)

type InitialHTMLAttrHook added in v0.400.0

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

InitialHTMLAttrHook is a function to call when an Element is initially rendered.

type Input

type Input struct {
	Tag  any
	Last atomic.Value // the last value received from the request
}

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]
}

func (*InputBool) JawsEvent

func (ui *InputBool) JawsEvent(e *jaws.Element, wht what.What, val string) (err error)

func (*InputBool) JawsUpdate

func (ui *InputBool) JawsUpdate(e *jaws.Element)

type InputDate

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

func (*InputDate) JawsEvent

func (ui *InputDate) JawsEvent(e *jaws.Element, wht what.What, val string) (err error)

func (*InputDate) JawsUpdate

func (ui *InputDate) JawsUpdate(e *jaws.Element)

type InputFloat

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

func (*InputFloat) JawsEvent

func (ui *InputFloat) JawsEvent(e *jaws.Element, wht what.What, val string) (err error)

func (*InputFloat) JawsUpdate

func (ui *InputFloat) JawsUpdate(e *jaws.Element)

type InputText

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

func (*InputText) JawsEvent

func (ui *InputText) JawsEvent(e *jaws.Element, wht what.What, val string) (err error)

func (*InputText) JawsUpdate

func (ui *InputText) JawsUpdate(e *jaws.Element)

type IsJsVar

type IsJsVar interface {
	bind.RWLocker
	jaws.UI
	jaws.EventHandler
	PathSetter
}

type JsVar

type JsVar[T any] struct {
	bind.RWLocker
	Ptr *T
	Tag any
}

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.

func (*JsVar[T]) JawsEvent

func (ui *JsVar[T]) JawsEvent(e *jaws.Element, wht what.What, val string) (err error)

func (*JsVar[T]) JawsGet

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

func (*JsVar[T]) JawsGetPath

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

func (*JsVar[T]) JawsGetTag

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

func (*JsVar[T]) JawsRender

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

func (*JsVar[T]) JawsSet

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

func (*JsVar[T]) JawsSetPath

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

func (*JsVar[T]) JawsUpdate

func (ui *JsVar[T]) JawsUpdate(e *jaws.Element)

type JsVarMaker

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

type Label

type Label struct{ HTMLInner }

func NewLabel

func NewLabel(innerHTML bind.HTMLGetter) *Label

func (*Label) JawsRender

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

type Li

type Li struct{ HTMLInner }

func NewLi

func NewLi(innerHTML bind.HTMLGetter) *Li

func (*Li) JawsRender

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

type Number

type Number struct{ InputFloat }

func NewNumber

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

func (*Number) JawsRender

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

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 JawsClick is invoked.
	Clicked(fn ClickedHook) (newobj Object)

	// ContextMenu returns an Object that will call fn when JawsContextMenu
	// is invoked.
	ContextMenu(fn ContextMenuHook) (newobj Object)

	// InitialHTMLAttr returns an Object that will call fn when
	// JawsInitialHTMLAttr is invoked.
	InitialHTMLAttr(fn InitialHTMLAttrHook) (newobj Object)
}

func New added in v0.400.0

func New(innerHTML any) (obj Object)

New returns a new Object that will render HTML. innerHTML is passed to MakeHTMLGetter(), which may or may not provide tags.

type Option

type Option struct{ *named.Bool }

func NewOption

func NewOption(nb *named.Bool) Option

func (Option) JawsRender

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

func (Option) JawsUpdate

func (ui Option) JawsUpdate(e *jaws.Element)

type Password

type Password struct{ InputText }

func NewPassword

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

func (*Password) JawsRender

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

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 ErrValueUnchanged.
	JawsSetPath(elem *jaws.Element, jspath string, value any) (err error)
}

type Radio

type Radio struct{ InputBool }

func NewRadio

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

func (*Radio) JawsRender

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

type RadioElement

type RadioElement struct {
	// contains filtered or unexported fields
}

func (RadioElement) Label

func (re RadioElement) Label(params ...any) template.HTML

Label renders a HTML label element.

func (RadioElement) Radio

func (re RadioElement) Radio(params ...any) template.HTML

Radio renders a HTML input element of type 'radio'.

type Range

type Range struct{ InputFloat }

func NewRange

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

func (*Range) JawsRender

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

type Register

type Register struct{ jaws.Updater }

Register creates an element used for update-only registration.

func NewRegister

func NewRegister(updater jaws.Updater) Register

func (Register) JawsRender

func (ui Register) JawsRender(*jaws.Element, io.Writer, []any) error

type RequestWriter

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

func (RequestWriter) A

func (rw RequestWriter) A(innerHTML any, params ...any) error

func (RequestWriter) Button

func (rw RequestWriter) Button(innerHTML any, params ...any) error

func (RequestWriter) Checkbox

func (rw RequestWriter) Checkbox(value any, params ...any) error

func (RequestWriter) Container

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

func (RequestWriter) Date

func (rw RequestWriter) Date(value any, params ...any) error

func (RequestWriter) Div

func (rw RequestWriter) Div(innerHTML any, params ...any) error

func (RequestWriter) Get

func (rqw RequestWriter) Get(key string) (val any)

Get calls Request().Get()

func (RequestWriter) HeadHTML

func (rqw RequestWriter) HeadHTML() error

HeadHTML outputs the HTML code needed in the HEAD section.

func (RequestWriter) Img

func (rw RequestWriter) Img(imageSrc any, params ...any) error

func (RequestWriter) Initial

func (rqw RequestWriter) Initial() *http.Request

Initial returns the initial http.Request.

func (RequestWriter) JsVar

func (rqw RequestWriter) JsVar(jsvarname string, jsvar any, params ...any) (err error)

JsVar binds a JsVar[T] to a named Javascript variable.

You can also pass a JsVarMaker instead of a JsVar[T].

func (RequestWriter) Label

func (rw RequestWriter) Label(innerHTML any, params ...any) error

func (RequestWriter) Li

func (rw RequestWriter) Li(innerHTML any, params ...any) error

func (RequestWriter) Number

func (rw RequestWriter) Number(value any, params ...any) error

func (RequestWriter) Password

func (rw RequestWriter) Password(value any, params ...any) error

func (RequestWriter) Radio

func (rw RequestWriter) Radio(value any, params ...any) error

func (RequestWriter) RadioGroup

func (rw RequestWriter) RadioGroup(nba *named.BoolArray) (rel []RadioElement)

func (RequestWriter) Range

func (rw RequestWriter) Range(value any, params ...any) error

func (RequestWriter) Register

func (rqw 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. The updaters JawsUpdate method will be called immediately to ensure the initial rendering is correct.

Returns a Jid, suitable for including as a HTML "id" attribute:

<div id="{{$.Register .MyUpdater}}">...</div>

func (RequestWriter) Select

func (rw RequestWriter) Select(sh named.SelectHandler, params ...any) error

func (RequestWriter) Session

func (rqw RequestWriter) Session() *jaws.Session

Session returns the Requests's Session, or nil.

func (RequestWriter) Set

func (rqw RequestWriter) Set(key string, val any)

Set calls Request().Set()

func (RequestWriter) Span

func (rw RequestWriter) Span(innerHTML any, params ...any) error

func (RequestWriter) TailHTML

func (rqw 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

func (RequestWriter) Td

func (rw RequestWriter) Td(innerHTML any, params ...any) error

func (RequestWriter) Template

func (rqw RequestWriter) Template(name string, dot any, params ...any) error

Template renders the given template using ui.With as data.

The Dot field in ui.With is set to dot, and name is resolved to a *template.Template using Jaws.LookupTemplate().

func (RequestWriter) Text

func (rw RequestWriter) Text(value any, params ...any) error

func (RequestWriter) Textarea

func (rw RequestWriter) Textarea(value any, params ...any) error

func (RequestWriter) Tr

func (rw RequestWriter) Tr(innerHTML any, params ...any) error

func (RequestWriter) UI

func (rqw RequestWriter) UI(ui jaws.UI, params ...any) (err error)

func (RequestWriter) Write

func (rqw RequestWriter) Write(p []byte) (n int, err error)

type Select

type Select struct {
	ContainerHelper
}

func NewSelect

func NewSelect(sh named.SelectHandler) *Select

func (*Select) JawsEvent

func (ui *Select) JawsEvent(e *jaws.Element, wht what.What, val string) (err error)

func (*Select) JawsRender

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

func (*Select) JawsUpdate

func (ui *Select) JawsUpdate(e *jaws.Element)

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.
	JawsPathSet(elem *jaws.Element, jspath string, value any)
}

type Span

type Span struct{ HTMLInner }

func NewSpan

func NewSpan(innerHTML bind.HTMLGetter) *Span

func (*Span) JawsRender

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

type Tbody

type Tbody struct {
	ContainerHelper
}

func NewTbody

func NewTbody(c jaws.Container) *Tbody

func (*Tbody) JawsRender

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

func (*Tbody) JawsUpdate

func (ui *Tbody) JawsUpdate(e *jaws.Element)

type Td

type Td struct{ HTMLInner }

func NewTd

func NewTd(innerHTML bind.HTMLGetter) *Td

func (*Td) JawsRender

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

type Template

type Template struct {
	Name string // Template name to be looked up using Jaws.LookupTemplate()
	Dot  any    // Dot value to place in With structure
}

Template references a Go html/template to be rendered through JaWS.

The Name field identifies the template to execute and Dot contains the data that will be exposed to the template through the With structure constructed during rendering. Additional tag bindings and event handlers can be supplied at render time through the RequestWriter.Template helper.

func NewTemplate

func NewTemplate(name string, dot any) Template

NewTemplate constructs a Template with the provided name and data value.

It is a small helper that makes it convenient to use Template values with other JaWS helpers without having to fill the struct fields manually.

func (Template) JawsEvent

func (t Template) JawsEvent(e *jaws.Element, wht what.What, val string) error

func (Template) JawsRender

func (t Template) JawsRender(e *jaws.Element, wr io.Writer, params []any) (err error)

func (Template) JawsUpdate

func (t Template) JawsUpdate(e *jaws.Element)

func (Template) String

func (t Template) String() string

type Text

type Text struct{ InputText }

func NewText

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

func (*Text) JawsRender

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

type Textarea

type Textarea struct{ InputText }

func NewTextarea

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

func (*Textarea) JawsRender

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

type Tr

type Tr struct{ HTMLInner }

func NewTr

func NewTr(innerHTML bind.HTMLGetter) *Tr

func (*Tr) JawsRender

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

type With

type With struct {
	*jaws.Element                   // the Element being rendered using a template.
	RequestWriter                   // the RequestWriter
	Dot           any               // user data parameter
	Attrs         template.HTMLAttr // HTML attributes string
	Auth          jaws.Auth         // (optional) authentication information returned by MakeAuthFn
}

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