所以我正在尝试编写一个指令,将验证消息添加到被动表单的元素上。
假设我有以下组件模板:
<form [formGroup]="myForm">
<input type="text" [formControl]="myForm.controls['myText']" my-validation-messages>
</form>
以下组件逻辑:
@Component({
// Declarations go here...
})
class MyComponent {
myForm: FormGroup;
constructor(private fb: FormBuilder) {
// Constructor logic...
}
ngOnInit() {
this.myForm = this.fb.group({
"myText": ["", Validators.compose([Validators.pattern("[abc]*"), Validators.minLength(10)]
});
}
}
以下指令逻辑:
@Directive({
selector: ["my-validation-messages"]
})
export class MyValidationMessagesDirective {
@Input() formControl: FormControl;
element: HTMLInputElement;
constructor(private elm: ElementRef) {
// Constructor logic...
}
ngOnInit(): {
this.element = this.elm.nativeElement;
}
@HostListener("input") onInput(): {
if (!this.formControl.pristine && !this.formControl.valid) {
// Make validation message here.
}
}
}
似乎如果我将模式和minLength属性放在模板而不是组件中,我可以通过this.element.pattern和this.element.minLength获取指令中的实际模式和minLength值。如果我将它们从模板中删除,则访问器将按预期返回null。 (这也适用于其他验证器属性,例如:required和min。)
因此在指令中,我可以使用formControl中的任何内容来获取实际模式和minLength值以形成特定的验证消息(例如:“此字段只能接受a,b或c。”和“你需要输入超过10个字符。“)?或者我必须在模板中指定它们吗?
修改:
发现部分答案。所有表单控件都有这个对象(formControl.errors),基本上说明控件无效的原因。但是引用formControl.errors的方式有以下几种:
1)附加到表单控件的验证器函数必须在其返回对象中明确包含阈值。 Angular团队已经针对required,minLength,maxLength和pattern执行了此操作,并且必须以类似的方式设计任何自定义验证器函数。
/**
* minLength validator straight from @angular/forms/src/validators.ts.
* Note the 'requiredLength' property.
*/
static minLength(minLength: number): ValidatorFn {
return (control: AbstractControl): {[key: string]: any} => {
...
return length < minLength ?
{'minlength': {'requiredLength': minLength, 'actualLength': length}} :
null;
};
}
2)formControl.errors仅在表单控件无效时生成,否则为null。在我的情况下,我很好,因为我当时只想要属性值,但如果我想在任何其他时间对它们做些什么,这可能是一个问题;例如如果我想给元素一个占位符来描述该字段的预期值。
ngOnInit(): {
this.element = this.elm.nativeElement;
// this.formControl.errors = null;
}
@HostListener("input") onInput(): {
if (!this.formControl.pristine && !this.formControl.valid) {
// this.formControl.errors = {[key: string]: any};
let errors = "";
for (let reason in this.control.errors) {
errors += this.createValidationMessage(reason) + "/n";
}
}
}
createValidationMessage(reason: string): string {
switch(reason) {
case "minlength":
let minLength = this.formControl.errors['minlength']['requiredLength'];
return "You need to type more than " + minLength + " characters.";
...
case "required":
return "Please enter something into the field.";
/* The case names and how the attribute is referenced will depend on the validator
* function implementation; e.g. required returns just {required: true}, but minLength
* returns {requiredLength: X, actualLength: Y}.
*/
}
}
第一个限制只需要一个设计选择,但是我可以做些关于第二个限制吗? (即:formControl中是否有任何内容可用于从中提取属性值?再次,不在模板中指定它们。)