带有自定义组件的表单无法识别控件 [英] Form with Custom Component does not recognize control

查看:32
本文介绍了带有自定义组件的表单无法识别控件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用具有以下代码的自定义组件(自定义文本)

I am using a custom component (custom-text) which has the below code

    @Component({
      selector: 'custom-text, [custom-text]',
      templateUrl: './custom-text.template.html',
      styleUrls: ['./custom-text.component.scss']
    })
    export class CustomTextComponent implements OnInit {


      constructor() { }

      ngOnInit() {
      }
    }

Inside the custom-text.template.html

    <mat-form-field>
      <input matInput 
            id="controlid" 
            name="controlname" 
            maxlength="8"
            [(ngModel)]="value">
    </mat-form-field>

当我将此控件包含在另一个组件的表单(模板驱动)中时.

When I include this control inside a form (template-driven) on another component.

    <form #someForm="ngForm">
        <div custom-text></div>
    </form>

or 

<form #someForm="ngForm">
    <custom-text></custom-text>
</form>

我无法使用 someForm.controls['controlId'] 获取控件的实例

I am unable to get the instance of the control using someForm.controls['controlId']

我做错了什么.

推荐答案

我离开 stackblitz 最简单的基于素材输入的自定义表单控件.

I leave in stackblitz the most simple custom form control based in material input.

如您所见,实现了 ControlValueAccessor,它具有以下功能:

As you see implements ControlValueAccessor, that's has the functions:

onChange:any; //declare this function to indicate in any time that you change the value
onTouched:any; //declare this function to indicate in any time that your compoment is touched

 writeValue(value: any[]|any): void {
    this.value=value;
  }

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

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

  setDisabledState(isDisabled: boolean): void {
    this.disabled=isDisabled
  }

和像这样的供应商

   {
      provide: NG_VALUE_ACCESSOR,
      useExisting: forwardRef(() => CustomMat),
      multi: true
    }

如果要在组件内部进行验证,则需要添加一个新的提供程序

If you want to make a validation inside the component, you need add a new provider

   {
      provide: NG_VALIDATORS,
      useExisting: forwardRef(() => CustomMat),
      multi: true,
    }

并创建函数validate

And create the function validate

validate(control: AbstractControl): ValidationErrors | null{
      //your logic here
      return null;
  }

我又用了这两个函数:

setValue(value: any){
    this.value=value;
    this.onChange(value);

  }
  focusOut()
  {
    this.onTouched()
  }

调用更改和触摸函数

01.04.20 好,这个自定义材质输入的问题是错误看不到输入中的反映,所以我们要做一些改变

Updated 01.04.20 well, the problem of this custom material input is that the error can not see reflected in the input, so we are going to make some change

这个想法是添加一个 customError 匹配器

The idea is add a customError matcher

export class CustomFieldErrorMatcher implements ErrorStateMatcher {
  constructor(private customControl: AbstractControl,private errors:any) { }

  isErrorState(control: AbstractControl | null, form: FormGroupDirective | NgForm | null): boolean {
    return this.customControl && this.customControl.touched && this.customControl.invalid;
  }
}

如果控件无效,那是我们的内部输入无效.那么,很难知道这个控制"是什么.为此,我们在 ngAfterViewInit 中注入了 NgControl,这个 ngControl 将成为我们的控件,噗

That's our inner input is invalid if the control is invalid. Well, are a dificult that is know what is the this "control". For this, in ngAfterViewInit we inject the NgControl, and this ngControl will be our control, puff

ngAfterViewInit(): void {
    const ngControl: NgControl = this.injector.get(NgControl, null);
    if (ngControl) {
      setTimeout(() => {
        this.control = ngControl.control;
         this.matcher = new CustomFieldErrorMatcher(this.control,null);
      })
    }
  }

至少添加这个匹配器

  <input name="input" matInput [ngModel]="value"
    (ngModelChange)="setValue($event)" 
    [errorStateMatcher]="matcher" >

你可以在这个stackblitz

这篇关于带有自定义组件的表单无法识别控件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆