如何使用模板表单从 Angular 2 中的父组件触发子组件验证器
How to trigger child component validators from parent component in Angular 2 using template 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,用户可以在其中选择他们喜欢的联系方式。如果用户 select "email",则必须输入电子邮件。
如您所见,请注意父项中存在一些逻辑 emailRequired
根据当前 selected 首选联系方式动态计算电子邮件输入是否强制的功能。
每当这个 selected 值发生变化时,我都需要以某种方式触发电子邮件输入验证器。我怎样才能做到这一点?
使用 @ViewChild 我设法从 MyFormComponent 获取了 EmailInputComponent。但我现在不知道如何进行...
我认为你不需要在前面指定attr
来引用required
属性。
尝试简单的,
[required]="required ? '' : null"
如果仍然无效,可能是因为“@Input”required
属性 未在 EmailInputComponent 中更新。因此,@naeramarth7 建议在 EmailInputComponent 的 ngOnChanges
挂钩中查找它并更新。
ngOnChanges(changes: SimpleChange) {
for (let prop in changes) {
if(prop === 'required') {
this.required = changes[prop].currentValue;
}
}
}
确保在使用它时将 implements OnChanges
添加到 EmailInputComponent 声明中,并在 email-input.component.ts
同时我找到了解决办法。我的子组件现在引用相应的 FormGroup。
<email [(emailAddress)]="model.email"
[formGroup]="form.form"
[required]="emailRequired()">
</email>
通过 FormGroup,您可以到达子组件实际的 FormControl 并在验证器标志的 setter 内调用 updateValueAndValidity(set在我的例子中需要):
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
}
}
}
我在 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,用户可以在其中选择他们喜欢的联系方式。如果用户 select "email",则必须输入电子邮件。
如您所见,请注意父项中存在一些逻辑 emailRequired 根据当前 selected 首选联系方式动态计算电子邮件输入是否强制的功能。 每当这个 selected 值发生变化时,我都需要以某种方式触发电子邮件输入验证器。我怎样才能做到这一点?
使用 @ViewChild 我设法从 MyFormComponent 获取了 EmailInputComponent。但我现在不知道如何进行...
我认为你不需要在前面指定attr
来引用required
属性。
尝试简单的,
[required]="required ? '' : null"
如果仍然无效,可能是因为“@Input”required
属性 未在 EmailInputComponent 中更新。因此,@naeramarth7 建议在 EmailInputComponent 的 ngOnChanges
挂钩中查找它并更新。
ngOnChanges(changes: SimpleChange) {
for (let prop in changes) {
if(prop === 'required') {
this.required = changes[prop].currentValue;
}
}
}
确保在使用它时将 implements OnChanges
添加到 EmailInputComponent 声明中,并在 email-input.component.ts
同时我找到了解决办法。我的子组件现在引用相应的 FormGroup。
<email [(emailAddress)]="model.email"
[formGroup]="form.form"
[required]="emailRequired()">
</email>
通过 FormGroup,您可以到达子组件实际的 FormControl 并在验证器标志的 setter 内调用 updateValueAndValidity(set在我的例子中需要):
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
}
}
}