2

I'm using mat-datepicker and the user is able to manually enter in a date. I would like to be able to do something like this to validate the date and make sure it follows the pattern of MM/DD/YYYY:

const dobRegex: RegExp = /((?:0[1-9])|(?:1[0-2]))\/((?:0[0-9])|(?:[1-2][0-9])|(?:3[0-1]))\/(\d{4})/;
public dob: FormControl = new FormControl(null, Validators.compose( [ Validators.required, Validators.pattern(dobRegex)]));

However, when I do the above it doesn't work because mat-datepicker is converting any input with numbers into a Date object. Any other input that aren't numbers will convert it to null.

public date(c: FormControl) {
   console.log(c.value) // This value is already a Date object or null
}

Is there a way in which I can validate the manually entered text using pattern?

2 Answers 2

4

You can solve the error by setting the minimum Value of input to be 10 characters long and the maximum value of Input to be 10 characters.Then when you enter a numeral, the date-picker will validate the date and also whether it is 10 characters long.

Another method is by overriding the mat-date pickers parsing method by providing a custom component in your module.

providers: [{ provide: DateAdapter, useClass: UserDateAdapter },]

Then in the component

import { NativeDateAdapter, DateAdapter } from '@angular/material';

export class UserDateAdapter extends NativeDateAdapter {
parse(value: any): Date | null {
 //Your custom parse method 
 if ((typeof value === 'string') && (value.indexOf('/') > -1) && 
      value.length == 10) {
        const str = value.split('/');
        const year = Number(str[2]);
        const month = Number(str[0]) - 1;
        const date = Number(str[1]);
        return new Date(year, month, date);
  } else {
         return new Date(undefined);
  }
}
Sign up to request clarification or add additional context in comments.

6 Comments

Doesn't exactly solve the problem but I'll accept the answer anyways since it seems like there isn't a good way to validate manual input using a regex. The solution I ended up doing was using Moment and validating it by using by getting the creationData().
The solution you ended up doing was using Moment and validating it by using by getting the creationData(). can you explain or share the code like how you resolve it by using creationData()?
We don't need to use moment. I have updated the solution. We are actually overriding the native data adapter's parse method.
The first method (min and max length both set to 10) doesn't work for me - the input is parsed as a date and made into 10 characters before validation.
Use the second method, it returns the date as an invalid date when we do new Date(undefined). So you have to only validate whether the date is valid.
|
1

Hacky solution that I used switching to Moment.

import { AbstractControl } from '@angular/forms';
import * as moment from 'moment';

import { RegEx } from 'app/consts/regex.const';

export class DateValidator {
  public static isValidFormat(control: AbstractControl) {
    if (moment.isMoment(control.value)) {
      const input = control.value.creationData().input;
      if (typeof input === 'string' && (RegEx.DATE).test(input)
          || typeof input === 'object' && input.hasOwnProperty('year') && 
          input.hasOwnProperty('month') && input.hasOwnProperty('date')) {
        return null;
      }
    }

    if (!control.value && control.errors && control.errors.matDatepickerParse) {
      const datePickerText = control.errors.matDatepickerParse.text;
      if (!datePickerText) {
        return null;
      }
    }

    return { pattern: true };
  }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.