[英]Require one from two fields using Angular 2
我正在尝试创建一个联系表单。 表单如下所示:
<form novalidate [formGroup]="contact" (ngSubmit)="send()">
<p>
<label>Name
<br>
<input type="text" class="input" value="" formControlName="name">
<span class="error">Enter your name</span>
</label>
</p>
<p>
<label>E-mail
<br>
<input type="email" class="input" value="" formControlName="email">
<span class="error">It looks like this email is invalid</span>
</label>
</p>
<p>
<label>Phone
<br>
<input type="text" class="input" value="" formControlName="telefone">
<span class="error">It looks like this phone number is invalid</span>
</label>
</p>
<p>
<label>Message
<br>
<textarea type="text" class="input" value="" formControlName="message"></textarea>
<span class="error">The message can't be empty</span>
</label>
</p>
<p class="submit">
<input type="submit" name="submit" class="bt" value="Send">
</p>
</form>
在此表单中,只需要消息和名称以及电子邮件或电话号码字段。
我正在使用formBuilder
类,所以这里是TypeScript代码:
this.contact = this.formBuilder.group({
name: ['', Validators.required],
email: ['', Validators.compose([/*Use custom validador??*/])],
phone: ['', Validators.compose([/*Use custom validador??*/]],
message: ['', Validators.required]
});
我尝试使用自定义验证器作为解决方案,但我无法找到解决方案。 有什么建议?
我创建了一个自定义验证器指令:
import {
FormGroup,
ValidationErrors,
ValidatorFn,
Validators,
} from '@angular/forms';
export const atLeastOne = (validator: ValidatorFn, controls:string[] = null) => (
group: FormGroup,
): ValidationErrors | null => {
if(!controls){
controls = Object.keys(group.controls)
}
const hasAtLeastOne = group && group.controls && controls
.some(k => !validator(group.controls[k]));
return hasAtLeastOne ? null : {
atLeastOne: true,
};
};
要使用它,您只需执行以下操作:
this.form = this.formBuilder.group({
name: ['', Validators.required],
email:[''],
telefone:[''],
message:['', Validators.required],
}, { validator: atLeastOne(Validators.required, ['email','telefone']) });
因此,这里需要email
或telefone
。 如果你把它留空,那么任何带有值的控件都可以,你可以将它用于任何类型的验证器,而不仅仅是Validators.required
。
这可以任何形式重复使用。
是的,自定义验证器是可行的方法。
使您的表单组像这样:
this.contact = this.formBuilder.group({
name: ['', Validators.required],
email: ['', Validators.required],
phone: ['', Validators.required],
message: ['', Validators.required]
}, {validator: this.customValidationFunction})
然后让customValidationFunction
检查验证。 仅举例来说:
customValidationFunction(formGroup): any {
let nameField = formGroup.controls['name'].value; //access any of your form fields like this
return (nameField.length < 5) ? { nameLengthFive: true } : null;
}
像这样更改每个输入(将p标签更改为div。替换每个输入的控件名称,并在适当的情况下更改隐藏span标记验证的语法):
<div [ngClass]="{'has-error':!contact.controls['name'].valid && contact.controls['name'].touched}">
<label>Name</label>
<input class="input" type="text" [formControl]="contact.controls['name']">
<span [hidden]="!contact.hasError('nameLengthFive')" class="error">Enter your name</span>
</div>
我已更新我的验证器代码段以支持字符串和数字类型
我受到托德斯凯尔顿的启发。 这是一个非常简单的验证器,可以满足您的要求,而不是其他任何内容:
/** * Validates if at least one of the provided fields has a value. * Fields can only be of type number or string. * @param fields name of the form fields that should be checked */ export function atLeastOne(...fields: string[]) { return (fg: FormGroup): ValidationErrors | null => { return fields.some(fieldName => { const field = fg.get(fieldName).value; if (typeof field === 'number') return field && field >= 0 ? true : false; if (typeof field === 'string') return field && field.length > 0 ? true : false; }) ? null : ({ atLeastOne: 'At least one field has to be provided.' } as ValidationErrors); }; }
以下是我如何使用它:
ngOnInit(): void { this.form = this.formBuilder.group( { field: [this.field], anotherField: [this.anotherField], }, { validator: atLeastOne('field','anotherField') }, ); }
稍微重构弗洛里安对懒惰的回答,因为它让ts-sonar愤怒(认知复杂性规则):
const isFieldEmpty = (fieldName: string, fg: FormGroup) => {
const field = fg.get(fieldName).value;
if (typeof field === 'number') { return field && field >= 0 ? true : false; }
if (typeof field === 'string') { return field && field.length > 0 ? true : false; }
};
export function atLeastOne(...fields: string[]) {
return (fg: FormGroup): ValidationErrors | null => {
return fields.some(fieldName => isFieldEmpty(fieldName, fg))
? null
: ({ atLeastOne: 'At least one field has to be provided.' } as ValidationErrors);
};
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.