我有一个简单的反应形式:
home.component.html
<div class="jumbotron">
<h2>Form with Validations</h2>
<form novalidate [formGroup]="complexForm" (ngSubmit)="submitForm(complexForm.value)">
<div class="form-group" [ngClass]="{'has-error':!complexForm.controls['firstName'].valid && complexForm.controls['firstName'].touched}">
<label>First Name:</label>
<custom-input name="firstName" [formControl]="complexForm.controls['firstName']" [(ngModel)]="firstName"></custom-input>
<div *ngIf="complexForm.controls['firstName'].hasError('required') && complexForm.controls['firstName'].touched" class="alert alert-danger">You must include a first name.</div>
</div>
<div class="form-group">
<button type="submit" class="btn btn-primary" [disabled]="!complexForm.valid">Submit</button>
</div>
</form>
</div>
home.component.ts
import { Component } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
@Component({
selector: 'app-home',
templateUrl: './home.component.html',
})
export class HomeComponent {
complexForm: FormGroup;
constructor(fb: FormBuilder) {
this.complexForm = fb.group({
'firstName': [null, Validators.required]
})
console.log(this.complexForm);
this.complexForm.valueChanges.subscribe((form: any) => {
console.log('form changed to:', form);
}
);
}
submitForm(value: any) {
console.log(value);
}
}
......自定义输入组件......
custominput.component.ts
import { Component, Input, forwardRef } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
const noop = () => { };
const CUSTOM_INPUT_CONTROL_VALUE_ACCESSOR: any = {
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => CustomInputComponent),
multi: true
};
@Component({
selector: 'custom-input',
template: `<input class="form-control"
[(ngModel)]="value" name="somename"
(blur)="onTouched()">`,
//templateUrl: './custominput.component.html'
providers: [CUSTOM_INPUT_CONTROL_VALUE_ACCESSOR]
})
export class CustomInputComponent implements ControlValueAccessor {
private _value: any = '';
private _onTouchedCallback: () => void = noop;
private _onChangeCallback: (_: any) => void = noop;
get value(): any { return this._value; };
set value(v: any) {
if (v !== this._value) {
this._value = v;
this._onChangeCallback(v);
}
}
onTouched() {
this._onTouchedCallback();
}
writeValue(value: any) {
if (value !== undefined) {
this._value = value;
}
}
registerOnChange(fn: any) {
this._onChangeCallback = fn;
}
registerOnTouched(fn: any) {
this._onTouchedCallback = fn;
}
}
......和一个自定义验证器......
emailvalidator.ts
import { Directive, forwardRef } from '@angular/core';
import { NG_VALIDATORS, FormControl } from '@angular/forms';
function validateEmailFactory() {
return (c: FormControl) => {
let EMAIL_REGEXP = /^[a-z0-9!#$%&'*+\/=?^_`{|}~.-][email protected][a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$/i;
return EMAIL_REGEXP.test(c.value) ? null : {
validateEmail: {
valid: false
}
};
};
}
@Directive({
selector: '[validateEmail][ngModel],[validateEmail][formControl]',
providers: [
{ provide: NG_VALIDATORS, useExisting: forwardRef(() => EmailValidator), multi: true }
]
})
export class EmailValidator {
validator: Function;
constructor() {
this.validator = validateEmailFactory();
}
validate(c: FormControl) {
return this.validator(c);
}
}
我的目标是有可能以模板驱动的形式和被动形式模式声明我的自定义验证器(EmailValidator) . 到目前为止,我设法让它只在第一个工作,但我无法弄清楚如何在一个被动的形式上实现它 . 我哪里做错了?