Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AngularJS directive to prevent input of invalid date

What I want is for the user to only type in a valid date, however I'm having trouble figuring out a good way to accomplish that.

The date format needs to be "MM/DD/YYYY", so I have a mask on the input as "99/99/9999". While this forces the user to type only digits and automatically formats it in the way I need, the problem is this allows the user to type in something like "53/49/6540", which is an invalid date.

Attempt 1

Binding a function to the keypress/keydown event.

  • I have a regex that can validate the date as they type (so it allows "12" but not "13" for the month, for example).
  • All looks good.. but... starts showing some weird results when you edit
    • Let's say the input is "10/21/1999"
    • They want to change the month to "12".
    • So they put their cursor after the "0" and hit backspace,
    • Value is now "12/11/999 " and invalid, preventing input
    • Or, they simply highlight "0" and accidentally hit "3" instead of "2", it will go through, becoming "13/21/1999" then be invalid, preventing further input

Attempt 2

Binding a function to the keyup/changed event.

  • I get the old value, the new value and validate it, and revert back to the old if it's invalid
  • This creates a weird user experience as they watch what they typed in get removed and set back, which I do not like at all
  • Doesn't let the user backspace if invalid, since it reverts it
  • Still lets invalid data through if typed fast enough

Help

Is there any way at all to validate the date as they type it (rather than after the fact) without having weird things happen?

Plunkr showing issues: http://embed.plnkr.co/0qbiiiRnIo9SuJ5xNe30/preview

like image 233
Kari Avatar asked Nov 10 '22 16:11

Kari


1 Answers

After playing around with it more, I was able to come up with a solution that I'm satisfied with. Thought I would share in case anyone was curious:

Plunkr: http://embed.plnkr.co/gE1WXaXsYI7zpWPkmvVS/preview

Basically, I stumbled on the "selectionStart" and "selectionEnd" properties of an element, which allows you to grab the index of where the new value will be inserted on a keypress. So I was able to get the "new value" so to speak, by taking the old value and inserting the character typed into the correct position, validate it, and prevent keypress on invalid.

Another thing I did differently is strip out all slashes and spaces that the masking was inserting (_ _ / _ _ / _ _ _ _) and changed my regex to only validate based on numbers ("12121900" for example), which allows the user to backspace/insert characters at any point without getting weird "123/19/90" sort of variations that would fail.

It's not completely perfect, but better at least.

like image 165
Kari Avatar answered Nov 14 '22 22:11

Kari