I have a formControl field that I created for date of birth (dob). My goal is to simply have my directive format my date field entry into MM/DD/YYYY when they enter a date using MMDDYYYY, which the directive does fine. I also have a validator on the dob field (using reactive form method), which is using a regular expression to validate that the entry is even a date.
The validator is marking that the form as having an error. When debugging, I've found that the directive is correctly updating the value of the input form, but upon continuing debugging the remaining code (built-in Angular) it appears that the remaining code (which appears to be the code that handles validation) still sees the old value (example 02022010). I am new to Angular and Javascript, so my only thought is maybe it is a scoping issue?
I've tried using only the validator without the directive at all to make sure that the pattern was registering correctly. The pattern is indeed validating the date field right, so I don't believe the Validator.pattern to be the issue here in the sense of a bad pattern.
The following post: Validate md-datepicker using formcontrol is closely related to mine but it didn't help me, nor am I using a datepicker or want a datepicker.
app.component.ts
import { Component } from '@angular/core';
import { FormsModule, ReactiveFormsModule, FormGroup, FormControl, Validators } from '@angular/forms';
@Component({
selector: 'app-root',
template: `
<form [formGroup]='searchForm'>
<input #firstNameField formControlName='firstName' placeholder="Enter first name">
<input #lastNameField formControlName='lastName' placeholder="Enter last name">
<input #dobField formControlName='dob' placeholder='MM/DD/YYYY' autocomplete="off" appDOBinput></form>
<div *ngIf="searchForm.controls['dob'].hasError('pattern')">Date is invalid</div>
`,
styleUrls: ['./app.component.scss']
})
export class AppComponent {
searchForm: FormGroup;
// tslint:disable-next-line: max-line-length
REGEX = RegExp('^(?:(?:10|12|0?[13578])/(?:3[01]|[12][0-9]|0?[1-9])/(?:1[8-9]\\d{2}|[2-9]\\d{3})|(?:11|0?[469])/(?:30|[12][0-9]|0?[1-9])/(?:1[8-9]\\d{2}|[2-9]\\d{3})|0?2/(?:2[0-8]|1[0-9]|0?[1-9])/(?:1[8-9]\\d{2}|[2-9]\\d{3})|0?2/29/[2468][048]00|0?2/29/[3579][26]00|0?2/29/[1][89][0][48]|0?2/29/[2-9][0-9][0][48]|0?2/29/1[89][2468][048]|0?2/29/[2-9][0-9][2468][048]|0?2/29/1[89][13579][26]|0?2/29/[2-9][0-9][13579][26])$');
constructor() {
this.searchForm = new FormGroup({
firstName: new FormControl(''),
lastName: new FormControl(''),
dob: new FormControl('', { validators: Validators.pattern(this.REGEX), updateOn: 'blur' })
});
}
}
date-input.directive.ts
import { Directive, HostListener } from '@angular/core';
import { NgControl } from '@angular/forms';
@Directive({
selector: '[formControlName] [appDOBinput]',
})
export class DateInputDirective {
constructor(public ngControl: NgControl) { }
@HostListener('ngModelChange', ['$event'])
onModelChange(event) {
this.onInputChange(event, false);
}
@HostListener('keydown.backspace', ['$event'])
keydownBackspace(event) {
this.onInputChange(event.target.value, true);
}
onInputChange(event, backspace) {
let newVal = event.replace(/\D/g, '');
if (backspace && newVal.length <= 6) {
newVal = newVal.substring(0, newVal.length - 1);
}
if (newVal.length === 0) {
newVal = '';
} else if (newVal.length <= 3) {
newVal = newVal.replace(/^(\d{0,2})/, '$1/');
} else if (newVal.length <= 4) {
newVal = newVal.replace(/^(\d{0,2})(\d{0,2})/, '$1/$2/');
} else {
newVal = newVal.replace(/^(\d{0,2})(\d{0,2})(\d{0,4})/, '$1/$2/$3');
}
console.log('value in directive: ' + newVal);
this.ngControl.valueAccessor.writeValue(newVal);
}
}
The console output from the directive is showing the correct output such as input 02022010 would output 02/02/2010. However, if I continue to debug step by step eventually (within a file like core.js) I'll see the value field as having 02022010 still. Once all the logic is complete, the output after the date field is 'Date is invalid'
It is almost like the logic involved with validation is still using the old value.