简体   繁体   English

如何使用模板表单从Angular 2的父组件中触发子组件验证器

[英]How to trigger child component validators from parent component in Angular 2 using template forms

I'm having trouble with conditional validation using template forms in Angular. 我在Angular中使用模板表单进行条件验证时遇到麻烦。 I've created a custom EmailInputComponent: 我创建了一个自定义的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>

which is hosted inside a parent MyFormComponent: 托管在父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>

The form also contains a SelectComponent where users can choose their preferred way of contact. 该表单还包含一个SelectComponent,用户可以在其中选择其首选的联系方式。 If users select "email", the email input becomes mandatory. 如果用户选择“电子邮件”,则必须输入电子邮件。

As you can, see there is some logic going on in the parents emailRequired function that dynamically calculates whether an email input is mandatory or not based on the currently selected preferred way of contact. 可以看到,父母的emailRequired函数中存在一些逻辑,该逻辑根据当前选择的首选联系方式动态计算电子邮件输入是否是强制性的。 Whenever this selected value changes I need to somehow trigger the email input validators. 每当此选定值更改时,我都需要以某种方式触发电子邮件输入验证器。 How can I do that? 我怎样才能做到这一点?

Using @ViewChild I managed to get a hold of the EmailInputComponent from the MyFormComponent. 使用@ViewChild,我设法从MyFormComponent获得了EmailInputComponent。 But I don't know how to proceed now... 但是我现在不知道该如何进行...

I don't think you need to specify attr in front to refer to the required property. 我认为您不需要在前面指定attr来引用required属性。

Try the simple, 试试简单的

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

And if it still didn't work, it is likely because of the '@Input' required property not getting updated in the EmailInputComponent. 如果仍然无法使用,则可能是由于EmailInputComponent中的'@Input' required属性未得到更新。 So as @naeramarth7 suggested look for it in the ngOnChanges hook of the EmailInputComponent and update. 因此,正如@ n​​aeramarth7建议的ngOnChanges ,请在EmailInputComponent的ngOnChanges挂钩中进行查找并进行更新。

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

make sure, when you use it, to add implements OnChanges to the EmailInputComponent declaration and also to import SimpleChange and OnChanges from ' @angular/core ' inside the email-input.component.ts 确保在使用时,将implements OnChanges添加到EmailInputComponent声明中,并确保从email-input.component.ts ' @angular/core '导入SimpleChangeOnChanges

Meanwhile I found a solution. 同时我找到了解决方案。 My child component now references the according FormGroup. 我的子组件现在引用了相应的FormGroup。

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

Via the FormGroup, you can then reach to the child components actual FormControl and call updateValueAndValidity inside the setter of the validator flag ( set required in my case): 然后,通过FormGroup,您可以到达子组件实际的FormControl,并在验证器标志的设置器中调用updateValueAndValidity (在我的情况下为必需设置 ):

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何从 angular 中的父组件触发子组件的 function? - How to trigger a function of child component from parent in angular? 父组件中的触发事件来自路由Angular中子组件的加载 - Trigger event in Parent component from child component load in routing Angular 在父组件中调用 Angular MatStepper Next 上的子验证器 - Calling Child Validators on Angular MatStepper Next in Parent Component 如何使用 React Hooks 从子组件 onClick() 触发父组件中的事件? - How to trigger an event in Parent Component from Child Component onClick() using React Hooks? 如何从 Angular 9 中的子组件访问父组件 - How to Access Parent Component from Child Component in Angular 9 Angular 2,如何将选项从父组件传递到子组件? - Angular 2, How to pass options from parent component to child component? 角路由器如何从父组件调用子组件 - angular router how to call child component from the parent component 如何从 Angular 中的父组件访问子组件? - How to access child component from parent component in Angular? 如何从 Angular 中的子路由组件访问父组件属性? - How to access parent component properties from a child route component in Angular? 如何使用<parent>和<child> angular 模板递归中的组件 - How to use <parent> and <child> component in template recursion in angular
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM