Controls share a consistent, signal-backed state model. It lives in two base classes:
JigBase<T> — the root of every control. Owns presentation/identity state:
unstyled, kind, color, and the pt passthrough input.ValueControlBase<T> — extends JigBase for form-value controls. Adds the value and
interaction state.ValueControlBase exposes these (all boolean inputs use Angular's booleanAttribute
transform, so <jig-checkbox disabled> works):
| Signal | Kind | Meaning |
|---|---|---|
value |
model() |
the control's value (two-way) |
disabled |
input() |
non-interactive, greyed |
readonly |
input() |
visible but not editable |
invalid |
input() |
failed validation styling |
touched |
model() |
has been focused/blurred |
dirty |
input() |
value has changed |
label / labelledBy / inputId |
input() |
accessibility wiring |
value and touched are two-way model()s; the rest are one-way inputs.
invalid is set by you, not derivedSetting [invalid] is an explicit choice — the control does not flip it automatically from
form validation. There is no ControlValueAccessor. Instead:
FormValueControl, so they bind directly and a
bound field writes invalid in for you.AbstractControl's errors/touched/dirty and drives a hint control, rather than
mutating the control's own invalid.When the invalid styling actually appears is a separate decision, owned by invalidOn
(touched by default, or dirty / immediate / never). The full picture is in
Forms & Validation.
State signals are wired to theme classes when a control calls injectThemeTemplate with a
mapping. Each entry is a class name mapped to a boolean or a callback that reads a
signal:
protected readonly theme = this.injectThemeTemplate(inputControlTemplate, {
root: true,
invalid: () => this.invalid(),
empty: () => !this.value(),
});When invalid() flips to true, the invalid theme class appears on the host — no manual
DOM code. The callbacks are re-evaluated reactively, so they must read signals to stay
live. This is the same mechanism Passthrough uses to apply classes.
unstyled cascades from a parent control to its children automatically. disabled is
composed where it makes sense — e.g. a radio button is disabled if either it or its group
is disabled, and an input-field marks its host inert when disabled so projected controls
follow.
jig