If you’ve been building custom form controls in Angular for a while, you know what to expect. You want to wrap a simple `<input>` or create a fancy custom slider, and suddenly you’re implementing `ControlValueAccessor` (CVA).

You have to implement `writeValue`, `registerOnChange`, `registerOnTouched`, and `setDisabledState`. You have to manage internal state, fire callbacks at the right time, and handle the boilerplate. It’s a rite of passage, but let's be honest: it’s a lot of code for something that should be simple.

Currently a custom input component with CVA looks something like this:

```
import { Component, forwardRef, input } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';

@Component({
  selector: 'app-custom-input',
  template: `
    <div class="custom-input-wrapper">
      @if (label()) {
        <label>{{ label() }}</label>
      }
      
      <input [type]="type()" [value]="value" [disabled]="isDisabled" (input)="onInput($event)" (blur)="onBlur()" style="padding: 8px; border: 1px solid #ccc; border-radius: 4px;">
    </div>
  `,
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      useExisting: forwardRef(() =&gt; CustomInputComponent),
      multi: true
    }
  ]
})
export class CustomInputComponent implements ControlValueAccessor {
  readonly label = input('');
  readonly type = input('text');

  // Internal state
  value: string = '';
  isDisabled: boolean = false;

  // Placeholder functions for Angular's callbacks
  onChange = (value: string) =&gt; {};
  onTouched = () =&gt; {};

  // --- ControlValueAccessor Implementation ---

  // 1. Called by Angular to write a value to the component (Model -&gt; View)
  writeValue(value: string): void {
    this.value = value || '';
  }

  // 2. Registers the callback Angular provides to listen for changes (View -&gt; Model)
  registerOnChange(fn: any): void {
    this.onChange = fn;
  }

  // 3. Registers the callback Angular provides to know when the control was interacted with
  registerOnTouched(fn: any): void {
    this.onTouched = fn;
  }

  // 4. (Optional) Called by Angular when the form control is disabled/enabled
  setDisabledState(isDisabled: boolean): void {
    this.isDisabled = isDisabled;
  }

  // --- UI Event Handlers ---

  onInput(event: Event): void {
    const target = event.target as HTMLInputElement;
    this.value = target.value;
    
    // Notify Angular that the value changed
    this.onChange(this.value); 
  }

  onBlur(): void {
    // Notify Angular that the input lost focus (marks the control as 'touched')
    this.onTouched(); 
  }
}
```

**That is about to change.**

With [**Pull Request #67267**](https://github.com/angular/angular/pull/67267), Angular is bridging the gap between the new Signal-Forms architecture and the Template/Reactive Forms. This isn't just a minor update—it’s a fundamental shift in how we author custom form controls.

## The New Way: `FormValueControl`

Imagine creating a custom input where the "form logic" is just… a Signal.

Thanks to this new PR, Angular now supports **Signal-Based** **FormValueControl** components via the `FormValueControl` interface (which means we can use the same component for all three Forms systems in Angular). The framework can now detect if your component exposes a `value` model signal and automatically sync it with `ngModel` or `FormControl`.

Here is the "Before" (CVA) vs. "After" (Signals):

### 🚫 The Old Way (ControlValueAccessor)

_(Trigger warning: Boilerplate)_

```
@Component({ ... })
export class OldInputComponent implements ControlValueAccessor {
  value: string = '';
  onChange = (val: string) =&gt; {};
  onTouched = () =&gt; {};

  writeValue(value: string): void {
    this.value = value;
  }
  registerOnChange(fn: any): void {
    this.onChange = fn;
  }
  registerOnTouched(fn: any): void {
    this.onTouched = fn;
  }
  // ... and don't forget the providers array!
}
```

### ✨ The New Way (Signal Forms)

_(Look at how clean this is!)_

```
@Component({
  selector: 'fancy-input',
  template: `
    <textarea [value]="value()" (input)="value.set($event.target.value)">    </textarea>
  `,
})
export class FancyInput implements FormValueControl<string> {
  // This is it. This is the API.
  value = model<string>(''); 
}</string></string>
```

And just like that, you can use it immediately in your forms:

```
<fancy-input ngmodel>

<fancy-input [formcontrol]="myControl">
<fancy-input formcontrolname="myField"></fancy-input></fancy-input></fancy-input>
```

## Why You Should Care?

### 1\. Zero Boilerplate

You won't have to register callbacks and manually fire `onChange` events. The `model()` signal handles the two-way binding naturally. Angular observes the signal and updates the form control, and vice-versa.

### 2\. Seamless Integration

This isn't a "new forms module" that requires you to rewrite your entire app. This PR adds support for these signal-based controls _inside_ existing Template and Reactive Forms. You can start building new controls this way today and drop them right into your existing `[formGroup]`.

### 3\. Automatic Status Sync

It’s not just about the value. This update ensures that validation status, "touched" state, and "dirty" state are all synchronized.

```
class MyFancyInput implements FormValueControl<string> {
  readonly value = model('');
  readonly disabled = input(false);
  readonly touched = input(false);
  readonly dirty = input(false);
  readonly valid = input(true);
  readonly invalid = input(false);
  readonly pending = input(false);
  readonly required = input(false);
  readonly errors = input<readonly any[]>([]);
}</readonly></string>
```

## The Future is Reactive

This change is a massive win for Developer Experience (DX). It lowers the barrier to entry for creating reusable form components and fully embraces Angular's Signal era.

Get ready to delete a lot of `registerOnChange` code! 🎉
