В чем разница синтаксиса ControlValueAccessor и banana в коробке при реализации двусторонней привязки?

#angular

#угловой

Вопрос:

Я только что узнал, что существует несколько способов реализации двусторонней привязки в пользовательском компоненте. Чего я не могу понять, так это разницы между ними. Когда я говорю, я предпочитаю использовать компонент, который использует синтаксис банана в коробке (с @input() и @Output() для модели), чтобы реализовать двустороннюю привязку, подобную этому компоненту

 @Component({  selector: 'app-first-component',  template: `  lt;pgt;input model value: {{ inputModel }}lt;/pgt;  lt;button (click)="clickHandler()"gt;Clearlt;/buttongt;  ` }) export class FirstComponentComponent {  @Input() inputModel: string;  @Output() inputModelChange = new EventEmitterlt;stringgt; ();   clickHandler(): void {  this.inputModel = '';  this.inputModelChange.emit(this.inputModel);  } }  

и тот, который реализует ControlValuAccessor вот так

 @Component({  selector: 'app-second-component',  template: `  lt;pgt;input model value: {{ inputModel }}lt;/pgt;  lt;button (click)="clickHandler()"gt;Clearlt;/buttongt;  `,  providers: [{  provide: NG_VALUE_ACCESSOR,  useExisting: forwardRef(() =gt; SecondComponentComponent),  multi: true  }] }) export class SecondComponentComponent implements ControlValueAccessor {  private inputModel: string;  private onChanged: (value: string) =gt; void = () =gt; {};   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 */} }  

I они используются в родительском компоненте, подобном этому

 lt;app-first-component [(inputModel)]="value"gt; lt;/app-first-componentgt;  lt;app-second-component [(ngModel)]="value"gt; lt;/app-second-componentgt;  

Как вы можете видеть, они используются одинаково и выполняют одну и ту же работу. Если да, то почему это так ControlValueAccessor ? Могу ли я что-нибудь сделать со вторым компонентом, что невозможно с первым?

Комментарии:

1. ControlValueAccessor используется специально для пользовательских элементов управления угловой формой

2. Я думаю, что единственная разница в том, что ControlValueAccessor интерфейс также позволяет связывать FormControl s, но другой синтаксис этого не делает, верно?

Ответ №1:

Процессор ControlValueAccessor (или компонент, реализующий этот интерфейс) используется Angular в качестве моста между собственным элементом управления формой (например, ввод, текстовое поле, переключатель и т. Д.) И угловым представлением «FormControl»( ссылка в GitHub: https://github.com/angular/angular/blob/b5ab7aff433a67cddaa55e621d17b1a1b07b57c2/packages/forms/src/directives/reactive_directives/form_control_directive.ts).

Реализуя интерфейс ControlValueAccessor, вы обеспечиваете, чтобы Angulars FormControl получал уведомления при обновлении собственного элемента формы и наоборот (при программном внесении изменений в FormControl обновляется собственный пользовательский интерфейс).

Angular включает в себя процессоры управления значениями для всех известных элементов HTML-формы. Но когда вы пытаетесь создать свой собственный элемент управления формой, который не построен из собственных элементов (или вы хотите обернуть какой-то пользовательский интерфейс от третьей стороны), тогда ваш компонент должен реализовать интерфейс ControlValueAccessors, чтобы сделать ваш пользовательский элемент управления формой пользовательского интерфейса управляемым с помощью угловых форм.

[ngModel] используется в формах, управляемых шаблонами, для создания двусторонней привязки данных (пожалуйста, обратите внимание, что она помечена как устаревшая, начиная с Angular V6 (см. Ссылку выше). Таким образом, весь замысел, стоящий за этими двумя вещами, отличается. Насколько я понимаю, [ngModel] работает, потому что рабочий механизм ControlValueAccessors уже существует.