API reference
Headless radio is a directive attached to input[tngRadio]. It preserves native radio semantics while exposing a stable state contract for readonly, invalid, and focus styling.
Directive attachment
html
<label class="radio-row">
<input tngRadio name="plan" value="starter" />
<span>Starter</span>
</label>
Grouped radio pattern
html
<fieldset class="radio-group">
<legend>Billing plan</legend>
<label class="radio-row">
<input tngRadio name="billing-plan" value="starter" />
<span>Starter</span>
</label>
<label class="radio-row">
<input tngRadio name="billing-plan" value="pro" [checked]="true" />
<span>Pro</span>
</label>
</fieldset>
| Input | Type | Default | Notes |
|---|---|---|---|
checked | boolean | '' | string | false | Controlled checked state for the individual radio. |
disabled | boolean | '' | string | false | Disables interaction and reflects native disabled semantics. |
readonly | boolean | '' | string | false | Keeps the radio focusable, but reverts user changes after interaction. |
required | boolean | '' | string | false | Reflects to the native required attribute. |
invalid, ariaInvalid | boolean | null | '' | 'true' | 'false' | null | Marks the control invalid and exposes the styling hooks. |
name, value | string | null | null | Use shared name values for a single-select radio group. |
ariaDescribedBy | string | null | null | Associates helper or error text with the radio. |
Reflected attributes
The directive reflects native and data attributes so your CSS can style state without relying on JavaScript-managed wrapper nodes.
| Attribute | When present | Purpose |
|---|---|---|
aria-checked | Always | Mirrors the checked state. |
aria-disabled, aria-readonly | When applicable | Communicates non-editable interaction state. |
data-state | Always | checked or unchecked hook for styling. |
data-checked, data-unchecked | Mutually exclusive | Convenience hooks for checked or unchecked visuals. |
data-invalid, data-disabled, data-readonly | When applicable | State hooks for validation and non-editable styling. |
data-focused, data-focus-visible | On focus | Differentiate generic focus from keyboard focus-visible treatment. |
Change handling
Headless radio does not emit a custom output. Listen to the native change event on the input, then update your selected value only when the browser reports the radio as checked.
Helper text association
html
<p id="billing-plan-help">Choose the plan that should ship with this environment.</p>
<label class="radio-row">
<input tngRadio name="billing-plan" ariaDescribedBy="billing-plan-help" />
<span>Starter</span>
</label>
In Angular examples, the common pattern is (change) plus a small guard: check event.target instanceof HTMLInputElement and then branch only when target.checked is true.