如何使用模板表单{Anging 2}从父组件触发子组件验证器

时间:2017-10-04 18:18:51

标签: javascript angular validation angular2-forms

我在使用Angular中的模板表单时遇到条件验证问题。我已经创建了一个自定义的EmailInputComponent:

<div class="form-group" provide-parent-form>
  <label for="email">Email<span *ngIf="required">*</span></label>
  <input id="email"
         class="form-control"
         name="email"
         type="email"
         [(ngModel)]="emailAddress"
         #email="ngModel"
         maxlength="255"
         validateEmail
         [required]="required ? '' : null"/>
  <error [model]="email" [referencedValue]="emailAddress"></error>
</div>

托管在父MyFormComponent中:

<form #form="ngForm" name="form" (ngSubmit)="onSubmit($event)">
  <fieldset>
    <email [(emailAddress)]="model.email" [required]="emailRequired()"></email> 
    <!-- select component here -->
  </fieldset>    
  <button type="submit" [disabled]="!form.form.valid">Send</button>
</form>

表单还包含一个SelectComponent,用户可以在其中选择首选的联系方式。如果用户选择&#34;电子邮件&#34;,则电子邮件输入将成为强制性的。

尽可能地看到父母 emailRequired 中存在一些逻辑 根据当前选择的首选联系方式动态计算电子邮件输入是否必需的功能。 每当此选定值更改时,我需要以某种方式触发电子邮件输入验证器。我怎样才能做到这一点?

使用 @ViewChild 我设法从MyFormComponent获取EmailInputComponent。但我现在不知道该怎么办......

2 个答案:

答案 0 :(得分:0)

我认为你不需要在前面指定attr来引用required属性。

试试简单,

 [required]="required ? '' : null"

如果它仍然不起作用,可能是因为&#39; @输入&#39; {PropertyInputComponent中未更新required属性。因此,@ naeramarth7建议在EmailInputComponent的ngOnChanges挂钩中查找并更新。

ngOnChanges(changes: SimpleChange) {
 for (let prop in changes) {
  if(prop === 'required') { 
   this.required = changes[prop].currentValue;
  }
 }
}

确保在使用时将implements OnChanges添加到EmailInputComponent声明中,并从SimpleChange&#39导入OnChanges@angular/core ;在email-input.component.ts

答案 1 :(得分:0)

同时我找到了解决方案。我的子组件现在引用了相应的FormGroup。

<email [(emailAddress)]="model.email" 
       [formGroup]="form.form" 
       [required]="emailRequired()">
</email>

通过FormGroup,您可以访问子组件实际的FormControl,并在验证器标志的设置器中调用 updateValueAndValidity (在我的情况下, set required ):< / p>

import {Component, EventEmitter, Input, Output} from '@angular/core';
import {FormGroup} from '@angular/forms';

@Component({
  selector: 'email',
  templateUrl: './email.component.html',
  styleUrls: ['./email.component.css']
})
export class EmailInputComponent {

  private _emailAddress: string;

  public _required = true;

  @Input()
  private formGroup: FormGroup;

  @Output()
  emailAddressChange = new EventEmitter();

  constructor() { }

  @Input()
  get emailAddress(): string {
    return this._emailAddress;
  }

  set emailAddress(value: string) {
    this._emailAddress = value;
    this.emailAddressChange.emit(this._emailAddress);
  }

  @Input()
  get required(): boolean {
    return this._required;
  }

  set required(value: boolean) {
    this._required = value;
    // this is where the magic happens
    const refEmailControl = this.formGroup.controls.email;
    if (refEmailControl) {
      refEmailControl.updateValueAndValidity(); // updates the validity state      
      refEmailControl.markAsTouched(); // necessary in my case to make UI render error message
    }
  }
}