Acabo de descubrir que hay varias formas de implementar un enlace bidireccional en un componente personalizado. Lo que no puedo entender es la diferencia entre ellos. ¿Cuándo debería preferir usar un componente que use banana en una sintaxis de cuadro (con @input() y @Output() para el modelo), para implementar un enlace bidireccional como este componente?
@Component({ selector: 'app-first-component', template: ` <p>input model value: {{ inputModel }}</p> <button (click)="clickHandler()">Clear</button> ` }) export class FirstComponentComponent { @Input() inputModel: string; @Output() inputModelChange = new EventEmitter<string> (); clickHandler(): void { this.inputModel = ''; this.inputModelChange.emit(this.inputModel); } } y uno que implementa ControlValuAccessor así
@Component({ selector: 'app-second-component', template: ` <p>input model value: {{ inputModel }}</p> <button (click)="clickHandler()">Clear</button> `, providers: [{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => SecondComponentComponent), multi: true }] }) export class SecondComponentComponent implements ControlValueAccessor { private inputModel: string; private onChanged: (value: string) => void = () => {}; clickHandler(): void { this.inputModel = ''; this.onChanged(this.inputModel); } registerOnChange(fn: any): void { this.onChanged = fn; } writeValue(value: string) { this.inputModel = value; this.onChanged(this.inputModel); } registerOnTouched(): void {/* ignored */} }Se usan en un componente principal como este
<app-first-component [(inputModel)]="value"> </app-first-component> <app-second-component [(ngModel)]="value"> </app-second-component> Como puede ver, se usan de la misma manera y también hacen el mismo trabajo. Si es así, ¿por qué hay ControlValueAccessor ? ¿Hay algo que pueda hacer con el segundo componente que no sea factible con el primero?
Angular utiliza un ControlValueAccessor (o un componente que implementa esta interfaz) como puente entre un control de formulario nativo (como entrada, campo de texto, botón de radio, etc.) y la representación angular "FormControl" (enlace en GitHub: https:// github.com/angular/angular/blob/b5ab7aff433a67cddaa55e621d17b1a1b07b57c2/packages/forms/src/directives/reactive_directives/form_control_directive.ts ).
Al implementar la interfaz de ControlValueAccessor, se asegura de que Angulars FormControl reciba una notificación cuando el elemento de formulario nativo se actualice y viceversa (cuando realiza cambios en FormControl mediante programación, la interfaz de usuario nativa se actualiza).
Angular trae ControlValueAccessors para todos los elementos de formulario HTML conocidos. Pero cuando intenta crear su propio control de formulario, que no se construye a partir de los elementos nativos (o desea envolver alguna interfaz de usuario de un tercero), entonces su componente debe implementar la interfaz ControlValueAccessors para hacer que su control de formulario de interfaz de usuario personalizado sea manejable por formularios angulares .
[ngModel] se usa en formularios basados en plantillas para crear un enlace de datos bidireccional (tenga en cuenta que está marcado como obsoleto desde Angular V6 (consulte el enlace anterior). Por lo tanto, la intención detrás de las dos cosas es diferente. Según tengo entendido, [ngModel] funciona porque ya existe un mecanismo ControlValueAccessors en funcionamiento.