astwerk

Forms and computed values

Two number inputs bound two-way, a total derived from them, and a checkbox driving visibility. The total is a x.Computed — recomputed in the browser whenever either input changes.

Total: 20

A checked box can drive visibility, too.

How it works

State

templ
var XPrice = x.NewSignal(10.0)
var XQty   = x.NewSignal(2.0)
var XTotal = x.Computed(XPrice.Mul(XQty))
var XTax   = x.NewSignal(false)

Two signals for the inputs; the total is derived from them with x.ComputedMul is a combinator compiled to JavaScript, so the total recomputes in the browser.

The inputs

templ
<p><label>Price</label> @x.Number(XPrice)</p>
<p><label>Quantity</label> @x.Number(XQty)</p>
<p class="demo-note"><span>Total: </span>@x.Text(XTotal)</p>

x.Number is two-way — typing writes the signal, setting the signal updates the field — and input that isn't a number is ignored. x.Text renders the computed total.

The checkbox

templ
<p>@x.Checkbox(XTax) <label>include tax</label></p>
@x.El("p", x.Show(XTax)) {
	A checked box can drive visibility, too.
}

x.Checkbox two-way binds a bool, and x.Show lets that same signal drive an element's visibility.

Full source
templ
var XPrice = x.NewSignal(10.0)
var XQty   = x.NewSignal(2.0)
var XTotal = x.Computed(XPrice.Mul(XQty))
var XTax   = x.NewSignal(false)

templ XFormsDemo() {
	<div class="demo">
		<p><label>Price</label> @x.Number(XPrice)</p>
		<p><label>Quantity</label> @x.Number(XQty)</p>
		<p class="demo-note"><span>Total: </span>@x.Text(XTotal)</p>
		<p>@x.Checkbox(XTax) <label>include tax</label></p>
		@x.El("p", x.Show(XTax)) {
			A checked box can drive visibility, too.
		}
	</div>
}

// On the page: @x.Document(XFormsDemo())
Why two-way doesn't feed back

Typing fires an input event that writes the signal; the reverse direction is a plain value assignment, which doesn't fire an input event. The two directions never chase each other.