具有自定义组件的窗体无法识别控件 [英] Form with Custom Component does not recognize control

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

问题描述

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

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']

我在做什么错了.

推荐答案

我留在

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(control: AbstractControl): ValidationErrors | null{
      //your logic here
      return null;
  }

我使用了另外两个功能:

I used this two more functions:

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将是我们的控件puff

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天全站免登陆