CngxRadioGroup
cngx-radio-group
projects/common/interactive/radio/radio-group.component.ts
Import#
import { CngxRadioGroup } from '@cngx/common/interactive'
Description#
Radio-group molecule that owns the canonical value for a set of
CngxRadio leaves and provides the parent contract via
CNGX_RADIO_GROUP. The group composes CngxRovingTabindex as a
host directive (with inputs: ['orientation'] exposed) so arrow-
key navigation across radios is wired from day one. Leaf
registration is imperative - register() / unregister() keep a
Map in declaration order so the group can resolve the active
radio by id without re-querying content children on every change
detection cycle.
Per W3C ARIA radio-group authoring practice, Tab enters the
group; arrow keys move focus AND select (auto-select variant);
Space/Enter also select the currently-focused radio. The group's
value is the source of truth; each leaf computes
radioChecked = computed(() => group.value() === radio.value())
against its own value input.
Auto-select wiring (no signal-write-in-effect). Per the
pillar §6 hard rule, the group does NOT subscribe to
CngxRovingTabindex.activeIndex via an effect that writes
value. Instead, the host CngxRovingTabindex raises its
navigation-key intent before it moves focus; the newly-focused
leaf's (focus) handler calls
group.consumePendingArrowSelect(this.value()), which reads
roving.consumeNavigationKey() and writes value (a signal write
inside a DOM event handler, not an effect - legal under the pillar
rules). Reading an already-set fact instead of a group-owned
(keydown) flag closes the one-press-behind race (#135).
Tab-into-group fires focus without a preceding navigation key, so
the hook reads false and no auto-select happens - Tab leaves the
consumer's value untouched.
<cngx-radio-group [(value)]="payment" name="payment-method">
<cngx-radio value="card">Card</cngx-radio>
<cngx-radio value="cash">Cash</cngx-radio>
<cngx-radio value="invoice" disabled>Invoice</cngx-radio>
</cngx-radio-group>Metadata#
Host#
Providers#
CNGX_RADIO_GROUP- useExisting
CngxRadioGroup CNGX_CONTROL_VALUE- useExisting
CngxRadioGroup CNGX_FORM_FIELD_CONTROL- useExisting
CngxRadioGroup
Relationships
Index#
Derived State
HostBindings
Inputs#
string | nullOptional id of an external error message element. When set, the
host emits aria-errormessage="<id>"; consumers MUST render an
element with that id. Default null skips the attribute.
Note: WAI-ARIA dictates that AT ignores this attribute when
aria-invalid is absent or "false", so a stable always-emitted
id is harmless when the field is valid.
nullBridge-writable invalid state. model<boolean> mirrors disabled
so external integrations (RF/Signal-Forms bridges, custom validity
adapters) can drive it without a parallel API path - consumers
typically read only.
falsestring | undefinedT | undefinedOutputs#
Bridge-writable invalid state. model<boolean> mirrors disabled
so external integrations (RF/Signal-Forms bridges, custom validity
adapters) can drive it without a parallel API path - consumers
typically read only.
T | undefinedInstance Properties#
Methods#
HostBindings#
| Binding | Expression |
|---|---|
[attr.id] | id() |
[attr.aria-label] | label() |
[attr.aria-disabled] | disabled() ? "true" : null |
[attr.aria-required] | required() ? "true" : null |
[attr.aria-invalid] | (invalid() || errorState()) ? "true" : null |
[attr.aria-errormessage] | errorMessageId() |
[attr.aria-orientation] | orientation() |
[attr.aria-busy] | ariaBusy() ? "true" : null |
[class.cngx-radio-group--horizontal] | orientation() === "horizontal" |
HostListeners#
| Event | Handler |
|---|---|
(focusin) | focusin() |
(focusout) | focusout() |
Default visuals for CngxRadioGroup. The host carries
.cngx-radio-group and frames a flex layout for projected
<cngx-radio> children. Stacks vertically by default. The scope
root pins vertical-align: top so the host doesn't shift when the
first leaf's indicator paints / unpaints its dot (the dot's
appearance changes the inline-flex baseline by ~2px).
Variants
--horizontal- flips to a row (no wrap, so consumers control overflow explicitly)
Inheritance
Gap cascades through the foundation:
--cngx-radio-group-gap->--cngx-space-sm
Layout
*0.5remGap between radio children. Falls back to --cngx-space-sm.