Angular — ввод, заключенный в пользовательский компонент, не работает в форме, управляемой шаблоном

#angular #angular-template-form

Вопрос:

Как и сказано в названии, если я помещаю ввод в свой пользовательский компонент, он не воспринимается шаблонной формой Angular. Вот stackblitz

Вот некоторый код из StackBlitz

app.component.html

 <div ngForm #myForm="ngForm">
  <app-custom-textbox
    customName="wrappedInput"
    customValue="wrapped"
  ></app-custom-textbox>
  <hr />
  <input name="noWrapper" [(ngModel)]="message" />
</div>
<hr />
<p>myForm.value is below:</p>
{{ myForm.value | json }}
 

custom-textbox.component.html

 <p>My custom textbox component</p>
<input type="textbox" name="{{ customName }}" [(ngModel)]="customValue" />
 

пользовательский-textbox.component.ts

 import { Component, Input } from '@angular/core';

@Component({
  selector: 'app-custom-textbox',
  templateUrl: './custom-textbox.component.html',
})
export class CustomTextboxComponent {
  @Input() customName: string = '';
  @Input() customValue: string = '';
}
 

Я ожидаю увидеть оба wrappedInput и noWrapper свойства в myForm.value выходных данных, но только noWrapper подбирается.

введите описание изображения здесь

Ответ №1:

Необходимо реализовать ControlValueAccessor для CustomTextBoxComponent, как показано ниже: ~

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

@Component({
  selector: 'app-custom-textbox',
  templateUrl: './custom-textbox.component.html',
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      useExisting: forwardRef(() => CustomTextboxComponent),
      multi: true,
    }
  ],
})
export class CustomTextboxComponent implements ControlValueAccessor {
  @Input() customValue: string = '';

  propagateChange = (_: any) => {};
  public onTouched: any = () => {};

  writeValue(obj: any): void {
    this.customValue = obj;
  }

  registerOnChange(fn: any): void {
    this.propagateChange = fn;
  }

  registerOnTouched(fn: any): void {
    this.onTouched = fn;
  }

  onModelChange(val: any) {
    this.propagateChange(val);
  }
}

 

Работает Stackblitz

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

1. Редактируемая ссылка StackBlitz: stackblitz.com/edit/angular-ivy-uittkj