在自定义 Angular 组件中访问 FormControl

Bee*_*jee 6 angular-components angular angular-reactive-forms

我正在创建一个自定义角度组件,当我的 FormControl(反应式表单)无效时,它会显示错误工具提示。但我不知道如何访问自定义组件中的 FormControl 以检查它是否被标记为有效。

我想要完成的

<div [formGroup]="form">
     <input formControlName="name" type="text" />
     <custom-validation-message formControlName="name">My special error message!</custom-validation-message>
  </div>
Run Code Online (Sandbox Code Playgroud)

已经遇到的东西

错误错误:没有名称的表单控件的值访问器:'surveyType'

通过使用 NG_VALUE_ACCESSOR 实现 ControlValueAccessor 来修复此问题,即使我不想更改该值。我还添加了一个注入器来访问 NgControl。

import { Component, OnInit, Injector } from '@angular/core';
import { NgControl, ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';

@Component({
    selector: 'custom-validation-message',
    templateUrl: './validation-message.component.html',
    providers: [{
        provide: NG_VALUE_ACCESSOR, multi: true, useExisting: ValidationMessageComponent
    }]
})
export class ValidationMessageComponent implements ControlValueAccessor, OnInit {
    public formControl: any;

    constructor(private injector: Injector) {
        super();
    }

    public ngOnInit(): void {
        const model = this.injector.get(NgControl);
        this.formControl = model.control;
    }

    public writeValue(obj: any): void {
    }
    public registerOnChange(fn: any): void {
    }
    public registerOnTouched(fn: any): void {
    }
    public setDisabledState?(isDisabled: boolean): void {
    }
}
Run Code Online (Sandbox Code Playgroud)

当前问题 model.control 未定义。检查模型后,我发现模型与空模型一样好,只有 _parent 是我表单的完整表示。model._parent.controls 确实包含我的表单的所有控件。但我仍然不知道当前的控制。

mal*_*awi 13

as I get you point you just want to make a componnet for display form control validation message the other answer explane why ControlValueAccessor is not the case here ,you just want to pass a control form reference to the component then check the validation state , Thomas Schneiter answer is a correct why but I face the case and it 's hard to keep get refrance by get method and sometime we are in sub group and form array so I idea is to just pass the name of the form control as string then get the control reference.

CustomValidationMessageComponent

@Component({
  selector: "custom-validation-message",
  templateUrl: "./custom-validation-message.component.html",
  styleUrls: ["./custom-validation-message.component.css"]
})
export class CustomValidationMessageComponent {
  @Input()
  public controlName: string;

  constructor(@Optional() private controlContainer: ControlContainer) {} 

  get form(): FormGroup {
    return this.controlContainer.control as FormGroup;
  }

  get control(): FormControl {
    return this.form.get(this.controlName) as FormControl;
  }
}
Run Code Online (Sandbox Code Playgroud)

template

<ng-container *ngIf="control && control?.invalid && control?.touched">
  <ul>
    <li *ngIf="control.hasError('required')">
      this is required field
    </li>
    <li *ngIf="control.hasError('pattern')">
      pattern is invalid 
    </li>
    <li *ngIf="control.hasError('maxlength')">
      the length is over the max limit
    </li>
     <!-- <li *ngFor="let err of control.errors | keyvalue">
       {{err.key}}
     </li> -->
  </ul>

</ng-container>
Run Code Online (Sandbox Code Playgroud)

and you can use it like this

<form [formGroup]="form">
 <label>
   First Name <input type="text" formControlName="firstName" />
   <div>
       <custom-validation-message controlName="firstName"></custom-validation-message>
   </div>
 </label>

 ...

</form>
Run Code Online (Sandbox Code Playgroud)

demo

you can check this angular library ngx-valdemort created by JB Nizet where it solve this problem perfectly .