CngxFormBridge
[formControl], [formControlName]
projects/forms/controls/form-bridge.directive.ts
Import#
import { CngxFormBridge } from '@cngx/forms/controls'
Description#
Lets cngx's value-bearing form atoms take part in Angular Reactive Forms exactly like
a native <input>: put [formControl] / [formControlName] on the atom and its value
flows into form.value, with validation, disabled and touched wired for free.
Without it a cngx-toggle or cngx-multi-chip-group would be inert to reactive forms.
This is the single ControlValueAccessor in cngx - it auto-applies by selector (you
never reference cngxFormBridge yourself) and talks to the host through
CNGX_CONTROL_VALUE, keeping the atoms themselves Forms-agnostic.
Covers, in both element and attribute form: cngx-toggle, cngx-checkbox,
cngx-radio-group, cngx-checkbox-group, cngx-button-toggle-group,
cngx-button-multi-toggle-group, cngx-chip-group, cngx-multi-chip-group, and
[cngxChipInteraction] (attribute only). Signal Forms ([field]) and the Level-3
select controls bypass this entirely - they provide CNGX_FORM_FIELD_CONTROL
directly. To bridge a bare self-contained external/Material CVA control into a cngx
field, see CngxBindField.
Behaviour:
- All four CVA hooks wrap their bodies in
untracked(). Load-bearing onregisterOnChange: the effect readscontrol.value()then invokesfn(value)outside the dependency graph, so any signalfntouches (today via RF internals, tomorrow via signal-based RF) does not feed back into the effect. registerOnChangeskips its first run - initial value is delivered viawriteValueper CVA contract.writeValuestampslastSeen; the change-listener short-circuits onObject.isso the RF→atom→RF round-trip never re-emits.
<!-- No bridge directive to add: it auto-attaches via selector to each atom below. -->
<form [formGroup]="form">
<cngx-toggle formControlName="notifications" />
<cngx-multi-chip-group formControlName="tags">
@for (t of pool; track t) {
<cngx-chip cngxChipInGroup [value]="t">{{ t }}</cngx-chip>
}
</cngx-multi-chip-group>
</form>
<!-- form.value is now { notifications: boolean; tags: string[] } -->Metadata#
Host#
Providers#
NG_VALUE_ACCESSOR- useExisting
forwardRef(() => CngxFormBridge)multi
Relationships
Depends on1
Index#
Methods#
registerOnChange(fn: function)Installs a tracked effect over control.value(). First run is the
post-mount baseline (CVA contract - initial value was delivered via
writeValue); every subsequent change forwards through fn(value)
inside untracked().
setDisabledState(isDisabled: boolean)RF → atom. Forwards the disabled flag into the atom's writable disabled signal.
HostListeners#
| Event | Handler |
|---|---|
(focusout) | focusout() |