【问题标题】:Angular - components inside form - formControlName must be used with a parentAngular - 表单内的组件 - formControlName 必须与父级一起使用
【发布时间】:2021-02-22 14:04:22
【问题描述】:

我想重用单个组件来动态生成表单输入字段并想出了这段代码

form-field.component.html

<label *ngIf="formLabel">{{formLabel}}</label>
<input
        type="text"
        class="form-control"
        [formControlName]="formFieldName"
        [ngClass]="{
              'is-invalid': formField.dirty && formField.errors
            }"
        [placeholder]="placeholder"
/>
<div
        *ngIf="formField.dirty && formField.errors"
        class="invalid-feedback"
>
<span *ngIf="formField.errors.required">
    {{requiredMessage}}
</span>
    <div *ngIf="formField.errors.pattern">
    <span *ngFor="let message of patternErrorMessages">
        {{message}}
    </span>
    </div>
</div>

form-field.component.ts

  @Input() formField: AbstractControl;
  @Input() patternErrorMessages: string[];
  @Input() formLabel: string;
  @Input() formFieldName: string;
  @Input() placeholder: string;
  @Input() form: FormGroup;

  requiredMessage = FORM_REQUIRED;

  constructor() { }

  ngOnInit(): void {
    this.patternErrorMessages = this.patternErrorMessages.length === 0 ? ['Pattern Mismatch'] : this.patternErrorMessages;
  }

父组件.html

<form (ngSubmit)="validSubmit(myFormGroup)" [formGroup]="myFormGroup">
         <div class="form-group">
          <app-form-field
                  [formField]="myFormGroup.controls.name"
                  [patternErrorMessages]="['Only Alphabets and Numbers are allowed.']"
                  [formLabel]="'Name'"
                  [placeholder]="'Enter Name'"
                  [form]="myFormGroup"
          >
          </app-form-field>
        </div>
</form>

我在调用它时遇到了这个错误。

ERROR Error: formControlName must be used with a parent formGroup directive.  You'll want to add a formGroup
           directive and pass it an existing FormGroup instance (you can create one in your class).

【问题讨论】:

    标签: javascript angular forms


    【解决方案1】:

    如果您想要自定义表单控件,请让它们从 @angular/forms 实现 ControlValueAccessor

    export interface ControlValueAccessor {
      writeValue(obj: any) : void;
      registerOnChange(fn: any) : void;
      registerOnTouched(fn: any) : void;
    }
    

    然后将组件注册到NG_VALUE_ACCESSOR令牌:

      providers: [
        { 
          provide: NG_VALUE_ACCESSOR,
          useExisting: forwardRef(() => MyAwesomeComponent(),
          multi: true
        }
      ]
    

    咆哮:

    退后一步,看看你在做什么。您正在尝试在表单控件之上构建一个统一层。

    您想对文本区域、数字输入、电子邮件输入重复此操作吗...?您打算添加多少条验证错误消息?他们的 i18n 呢?名单还在继续......

    您的代码不会比您要替换的代码复杂。

    帮自己一个忙,放弃那艘船。

    【讨论】:

      【解决方案2】:

      我想你忘了在 form-field.component.html 中添加formGroup

      将表单域包装在:

      <div [formGroup]="form">
       ...
      </div>
      

      【讨论】:

        【解决方案3】:

        对单个控件使用 formControl="YourFormControlName" 而不是 formControlName。对于分组控件,您始终需要一个 formGroup 父级。而且,在使用formControl时,你必须添加一个name和id属性。

        【讨论】:

          猜你喜欢
          • 2018-01-31
          • 2018-03-09
          • 2018-10-03
          • 2021-04-17
          • 2017-09-04
          • 2020-04-07
          • 1970-01-01
          • 2019-09-28
          • 2020-01-25
          相关资源
          最近更新 更多