将formControlName传递给Angular组件

时间:2019-06-13 12:49:32

标签: angular angular-reactive-forms angular-components controlvalueaccessor

我有一个反应式。设置与此类似:

myForm: FormGroup;

    this.myForm= new FormGroup({
        name: new FormControl("", [Validators.required, Validators.maxLength(15), Validators.pattern('...')]),
        ...
    });

我在这样的表单上使用它:

  <input
    type="text"
    formControlName="name"
  />
  <div *ngIf="name.errors?.required">
      Name is required
  </div>
  <div *ngIf="name.errors?.maxlength">
      Name must be {{ name.errors.maxlength.requiredLength }} characters        
  </div>
  <div *ngIf="name.errors?.pattern">
      Name has invalid characters.
  </div>

这只是我表格的简化版本。我有多个输入,并且必须为每个输入创建错误div。

因此,为了解决这个问题,我尝试创建一个组件。该组件与上面的代码非常相似:

  <input
    type="text"
    [formControlName]="formControlName"
  />
  <div *ngIf="name.errors?.required">
      Name is required
  </div>
  etc...

ts文件:

@Component({
  selector: 'app-text',
  templateUrl: './text.component.html'
})
export class TextComponent  {

  @Input() formControlName: FormControl;
}

因此在我的表单上,我想按以下方式使用此组件:

<app-text [formControlName]="name"></app-text>

但是我无法使用formControlName属性。

这可能吗?

谢谢

我快到了。

我已经创建了这个StackBlitz,所以请显示我的进度:

Demo

现在正在努力解决错误以及如何访问formControl来检查那些错误

2 个答案:

答案 0 :(得分:0)

您需要将表单控件传递给input元素,

  <input

    [value]="val"
    type="text"
    (input)="val=$event.target.value;onChange($event.target.value)"
    (blur)="onTouched()"
    [formControl]="control"

  >


  <span *ngIf="control && !control.valid && control.touched">
    <span class="error" *ngIf="control.errors['required']"> The field should not be empty</span>
    <span class="error" *ngIf="control.errors['email']"> The field should be an email 
    </span>
  </span>

从您的自定义组件中获取控件作为输入,并基于此显示错误。

@Component({
  selector: 'aep-textbox',
  templateUrl: './textbox.component.html',
  styleUrls: ['./textbox.component.scss'],
  providers: [
{
  provide: NG_VALUE_ACCESSOR,
  useExisting: forwardRef(() => TextboxComponent),
  multi: true
 }
]
})

 export class TextboxComponent extends DefaultValueAccessor implements OnInit {

 val:string = '';

 @Input('w-formcontrol') control;

 ngOnInit() {
 }

 writeValue(value: any): void {
  if(value) {
   this.val = value;
  }
 }
}

答案 1 :(得分:0)

如果您想访问formControl,最好使用NgControl作为DI

理由:

  • NgModel
  • FormControlDirective
  • FormControlName

NgControl的所有子类,因此,如果您这样做的话,将会对自己有很大帮助,因此,如果一路走来,您会改变主意,将formControl应用于NgControl等。您已经使用NgControl

覆盖了这些基础

因此,举例来说,它看起来像

import { Component, OnInit, Self } from '@angular/core';

import { NgControl } from '@angular/forms';

@Component({
  selector: 'app-text',
  templateUrl: './text-box.component.html',
  styleUrls: ['./text-box.component.css']
})
export class TextBoxComponent implements OnInit {

  constructor(@Self() private ngControl: NgControl) { }

  ngOnInit() {
    console.log(this.ngControl);
  }

}

HTML

<app-text[formControl]="control"></app-text>

我们使用@Self的原因是,该组件不会在注入器树的上方进一步寻找ngControl,而只能在其元素上找到。这样你就可以嵌套等等...

这对指令也是非常有益的,但到目前为止,我希望这对您有帮助!