Skip to main content
cngx-src documentation

CngxFormBridge

[formControl], [formControlName]

DirectivePrimaryv0.1.0WCAG AA

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 on registerOnChange: the effect reads control.value() then invokes fn(value) outside the dependency graph, so any signal fn touches (today via RF internals, tomorrow via signal-based RF) does not feed back into the effect.
  • registerOnChange skips its first run - initial value is delivered via writeValue per CVA contract.
  • writeValue stamps lastSeen; the change-listener short-circuits on Object.is so 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#

Relationships

Index#

Methods#

handleFocusOut#void
Protected

Fires onTouched when focus leaves the atom's host element.

registerOnChange#void
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().

@paramfnfunction
registerOnTouched#void
registerOnTouched(fn: function)
@paramfnfunction
setDisabledState#void
setDisabledState(isDisabled: boolean)

RF → atom. Forwards the disabled flag into the atom's writable disabled signal.

@paramisDisabledboolean
writeValue#void
writeValue(value: T)

RF → view. Stamps lastSeen then writes the atom's model signal; the change-listener short-circuits on Object.is and never routes the value back through onChange.

@paramvalueT

HostListeners#

EventHandler
(focusout)focusout()