«Нет средства доступа к значениям для элемента управления формой с именем» при создании повторно используемого компонента matInput с ControlContainer

#angular #angular-material #angular-reactive-forms #code-reuse #controlvalueaccessor

#angular #angular-материал #angular-reactive-forms #повторное использование кода #controlvalueaccessor

Вопрос:

Я следую этому руководству ControlContainer по созданию многоразовых форм, успешно создал группу многоразовых форм, но когда я попытался создать многоразовый элемент формы с matInput помощью, столкнулся с No value accessor ошибкой. Вот my-form-field.ts файл:

 import { Component, Input, OnInit } from '@angular/core';
import {
  ControlContainer,
  FormBuilder, FormControl,
  FormGroup,
  FormGroupDirective,
} from '@angular/forms';

@Component({
  selector: 'my-form-field',
  template: `
    <mat-form-field>
      <mat-label>{{label}}</mat-label>
      <input matInput [formControlName]="formControlName">
    </mat-form-field>
  `,
  viewProviders: [{ provide: ControlContainer, useExisting: FormGroupDirective }],
})
export class MyFormFieldComponent implements OnInit {
  @Input() formControlName: string;
  @Input() label: string;
  formGroup: FormGroup;

  constructor(private ctrlContainer: FormGroupDirective, private formBuilder: FormBuilder) {

  }

  ngOnInit(): void {
    this.formGroup = this.ctrlContainer.form;
    const control = new FormControl('');
    this.formGroup.addControl(this.formControlName, control);
  }
}
  

И вот как я это использую:

 <form [formGroup]='formGroup'>
  <my-form-field label='Test' formControlName='name'></my-form-field>
</form>
  

Воссоздал пример здесь:
https://stackblitz.com/edit/angular-9-material-reusable-matinput?file=src/app/my-form-field.ts

Мой подход может быть неправильным, поэтому предложение для повторно используемого компонента формы matInput тоже в порядке.

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

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

2. @MikeOne, нет, это не обязательно. Существует другой подход: опция, которая использует Envil (с использованием { provide: ControlContainer, useExisting: FormGroupDirective } или передает непосредственно FormControl.

3. Хорошо, спасибо, что дали мне знать. Я всегда использую ControlValueAccessor, не знал, что есть другой способ.

Ответ №1:

Вы используете в качестве имени @Input formControlName , это делает Angular запутанным, используйте другое имя, например controlName

 <my-form-field label='Test' controlName='name'></my-form-field>
  

И во вводе

 @Input('controlName') formControlName: string;