Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions lib/ui/input_widgets_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,16 @@ func TestInputFloatWidgets(t *testing.T) {
mustMatch(t, `^<input id="Jid\.[0-9]+" type="range" value="3.4">$`, got)
}

// TestRangeRendersExplicitBounds guards the documented workaround for the browser
// range defaults: min, max and step passed as params render verbatim after the
// value, letting a caller widen a domain the default 0..100 would otherwise clamp.
func TestRangeRendersExplicitBounds(t *testing.T) {
_, rq := newCoreRequest(t)
sf := newTestSetter(150.0)
_, got := renderUI(t, rq, NewRange(sf), `min="0"`, `max="200"`, `step="0.5"`)
mustMatch(t, `^<input id="Jid\.[0-9]+" type="range" value="150" min="0" max="200" step="0.5">$`, got)
}

// TestInputFloat_ReconcilesConvertedValues verifies that number and range inputs
// receive the canonical server value when a numeric adapter truncates or rounds
// an input to the value that was already stored.
Expand Down
15 changes: 14 additions & 1 deletion lib/ui/range.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,13 @@ type Range struct{ InputFloat }
// rendering or wire representation, so rendering, updating, or receiving one from
// the browser cancels the [jaws.Request] with a cause wrapping
// [jaws.ErrValueNotFinite].
//
// The widget emits no min, max, or step attribute of its own, so the browser
// applies the HTML range defaults min="0", max="100", step="1". A bound value
// outside that domain, or off the step grid, is silently clamped and rounded by
// the browser, and the adjusted value is echoed back through the setter on the
// next input event. Supply explicit min, max, and step attributes as render
// params when the defaults do not cover the bound value's domain.
func NewRange(g bind.Setter[float64]) *Range { return &Range{InputFloat{Setter: g}} }

// JawsRender renders ui as an HTML range input.
Expand All @@ -28,7 +35,13 @@ func (u *Range) JawsRender(elem *jaws.Element, w io.Writer, params []any) error

// Range renders an HTML range input.
//
// See [NewRange] for how a non-finite bound value is handled.
// Supply min, max, and step attributes in params when the browser defaults
// (min="0", max="100", step="1") do not cover the bound value's domain; a value
// outside it is silently clamped and rounded by the browser. For example:
//
// rw.Range(&v, `min="0"`, `max="200"`, `step="0.5"`)
//
// See [NewRange] for details and for how a non-finite bound value is handled.
func (rw RequestWriter) Range(value any, params ...any) error {
return rw.NewUI(NewRange(bind.MakeSetterFloat64(value)), params...)
}
Loading