$parsers / $formatters en Angular moderno
$parsers y $formatters pasan a ser las dos direcciones de un ControlValueAccessor: writeValue para modelo a vista, y el callback onChange registrado para vista a modelo.
Antes · AngularJS
app.directive('cents', function () {
return {
require: 'ngModel',
link: function (scope, el, attrs, ngModel) {
// model (cents) -> view (dollars)
ngModel.$formatters.push(function (cents) { return (cents / 100).toFixed(2); });
// view (dollars) -> model (cents)
ngModel.$parsers.push(function (text) { return Math.round(parseFloat(text) * 100); });
}
};
});Después · Angular@Component({
selector: 'app-money-input',
template: `<input #box [value]="text()" (input)="onInput(box.value)" (blur)="onTouched()" />`,
providers: [{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => MoneyInputComponent), multi: true }],
})
export class MoneyInputComponent implements ControlValueAccessor {
text = signal('');
private onChange: (cents: number) => void = () => {};
onTouched: () => void = () => {};
writeValue(cents: number | null) { this.text.set(((cents ?? 0) / 100).toFixed(2)); } // $formatters
registerOnChange(fn: (cents: number) => void) { this.onChange = fn; }
registerOnTouched(fn: () => void) { this.onTouched = fn; }
onInput(text: string) { this.onChange(Math.round(parseFloat(text) * 100)); } // $parsers
}Qué cambia
- La lógica de $formatters se muda a writeValue, que recibe el valor del modelo y actualiza lo que muestra el input.
- La lógica de $parsers corre con la entrada del usuario y pasa el valor ya convertido al callback de registerOnChange.
- El resultado es un componente o directiva que funciona con formControl, formControlName y ngModel.
Consejo de migración. Reserva ControlValueAccessor para inputs propios de verdad. Un parser que solo recorta o normaliza texto es más simple como una transformación aplicada al leer el valor del formulario.
Relacionado
¿Planeas una migración o una plataforma de microfrontends?
En una llamada de 20 minutos me cuentas tu situación y te digo cómo la abordaría. Si todavía no vale la pena, también te lo digo.
Escríbeme por LinkedIn