5

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

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,所以请展示我的进度:

演示

现在只是在努力解决错误以及如何访问 formControl 以检查这些错误

4

2 回答 2

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的原因是组件不会进一步查找注入器树来查找a ngControl,而只是查找它的元素。所以你可以嵌套等......

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

于 2019-06-13T13:23:34.860 回答
0

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

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

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

import { Component, OnInit, forwardRef, Input, OnChanges } from '@angular/core';
import { FormControl, ControlValueAccessor, NG_VALUE_ACCESSOR, NG_VALIDATORS } from '@angular/forms';

@Component({
  selector: 'app-test',
  templateUrl: './test.component.html',
  styleUrls: ['./test.component.css'],
  providers: [
    { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => TestComponent), multi: true }
  ]
})
export class TestComponent implements ControlValueAccessor, OnChanges {

  constructor() { }

  propagateChange:any = () => {};

   @Input() control: FormControl;
 @Input('messageValue') _messageValue = 'whateves';  

  get messageValue() {
    return this._messageValue;
  }

  set messageValue(val) {
    console.log('set messageValue', val)
    this._messageValue = val;
    this.propagateChange(val);
  }

hi(event) {
  console.log('hi');
  console.log(event)
  this.messageValue = event;
}
  ngOnInit() {
  }

  ngOnChanges(changes) {
    console.log('changes', changes);
    this.propagateChange(this.messageValue);
  }

    writeValue(value) {
      console.log('writeValue', value);
          if (value) {
            this.messageValue = value;
      }
    }


  registerOnChange(fn) {
    console.log('onChange')
    this.propagateChange = fn;
  }

  registerOnTouched() {}

}
于 2019-06-13T13:09:50.407 回答