0

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

    @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>

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

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

or 

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

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

我究竟做错了什么。

4

2 回答 2

1

我在stackblitz中留下了基于材料输入的最简单的自定义表单控件。

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

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
    }

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

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

并创建函数 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更新好了,这个自定义素材输入的问题是错误在输入中看不到反映,所以我们要做一些修改

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

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 将成为我们的控件,噗

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中看到

于 2019-04-26T09:44:17.140 回答
0

真正考虑您的问题,您不需要制作自定义表单组件,只需一个作为输入传递表单控件的组件。只需添加一个输入

@Input() control
//And in .html
<mat-form-field>
      <input matInput 
            id="controlid" 
            name="controlname" 
            maxlength="8"
            [formControl]="control">
</mat-form-field>

你使用的组件像

<form #someForm="ngForm">
    <div custom-text [control]="someForm.controls['controlId']"></div>
</form>
于 2019-04-26T09:58:12.040 回答