Angular2 v.2.3 - 访问活动表单的HTML5验证属性,而不指定模板

时间:2016-12-15 00:28:57

标签: angular angular2-forms

所以我正在尝试编写一个指令,将验证消息添加到被动表单的元素上。

假设我有以下组件模板:

<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中是否有任何内容可用于从中提取属性值?再次,不在模板中指定它们。)

0 个答案:

没有答案