2

I am trying to validate a form I have for age validating using javascript but it doesn't seem to be working.. not sure why.

Basically the date of birth is entered : dd/mm/yyyy and I need to make sure that in order to submit the form the age of the person is between 15 - 80.. I have tried validating this way but doesn't seem to work.

Html

<label>
    Date of birth:
    <input type="text" name="birth date" id="DOB" 
           placeholder="dd/mm/yyyy" maxlength="10" pattern="\d{1,2}\/\d{1,2}\/\d{4}" 
           required="required"/>
</label>

Javascript

var birthDate = document.getElementById("DOB").value;

if (2019 - birthDate < 15 || 2019 - birthDate > 80) {
  errMsg =errMsg + "your age must be between 15 and 80\n";
  result = false;
}

if (errMsg !== "") {
  alert(errMsg);
}

return result;
jo_va
  • 13,504
  • 3
  • 23
  • 47
Luca
  • 55
  • 1
  • 7
  • Is the element with id "DOB" an input with type date? Or what is it? – Anis R. Apr 30 '19 at 21:26
  • 3
    A little tip, when calculating somebody's age, you can't just use the year they were born. eg. If a baby was born `Dec 30 2018`, it not yet 1 is it?.. :) – Keith Apr 30 '19 at 21:27
  • @AnisR. its in a html page in a form – Luca Apr 30 '19 at 21:27
  • @Keith thanks for that didnt think that way but doesnt fix the issue im having haha – Luca Apr 30 '19 at 21:29
  • Possible duplicate of [Calculate age given the birth date in the format YYYYMMDD](https://stackoverflow.com/questions/4060004/calculate-age-given-the-birth-date-in-the-format-yyyymmdd) – Keith Apr 30 '19 at 21:31
  • 2
    if birthdate is a string in in the form `dd/mm/yyyy` - what makes you think you can subtract it from 2019 and javascript will *know you want the year* – Jaromanda X Apr 30 '19 at 21:32
  • @Keith i cant use JavaScript libraries .. is this considered one.. im new to most of this – Luca Apr 30 '19 at 21:33
  • 1
    1. use input type="date". 2. use `.valueAsDate` 3. use `.getFullyear` ....documentation here https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement and here https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date#Getter – Jaromanda X Apr 30 '19 at 21:35
  • 1
    The accepted answer in the duplicate link is not using any libraries, but like his disclaimer say for better results it much easier to use one.. – Keith Apr 30 '19 at 21:35
  • You should do this server side also, since it can be fooled this way – marsnebulasoup Apr 30 '19 at 21:40
  • @MarsNebulaSoup It can be "fooled" server side too since the user can enter any date they want. Really no reason to do this server side since you just have to assume the user is going to be truthful. – APAD1 Apr 30 '19 at 21:42
  • You should ALWAYS validate the input on the SERVER SIDE. The client side validation is only for giving the user immediate feedback that the input is valid or invalid. The client might not support validation (old browser, javascript disabled, etc) – some May 01 '19 at 00:24

5 Answers5

2

So, based on your comment, you have a text box as such:

<form>
    <input type="text" name="birth date" id="DOB" placeholder="dd/mm/yyyy" maxlength="10" pattern="\d{1,2}\/\d{1,2}\/\d{4}" required="required"/></label>
</form>

Therefore, document.getElementById("DOB").value; will be of the format dd/mm/yyyy.

So, if you are just checking the year, this should do the trick:

onload = function() {
    var form = document.getElementById("form"); //assuming this is your form's ID
    form.onsubmit = validate;
}

function checkAge() {
  var currentYear = new Date().getFullYear();
  var birthDate = document.getElementById("DOB").value;
  var errMsg = ""; //this line was missing from my code, and preventing it from working.

  //turning "dd/mm/yyyy" into an array of the form { "dd", "mm", "yyyy" }, and taking the "yyyy" part
  var birthYear = birthDate.split("/")[2];

  var age = currentYear - birthYear;
  if (age < 15 || age > 80) {
    errMsg =errMsg + "your age must be between 15 and 80\n";
    result = false;
  }

  if (errMsg !== "") {
    alert(errMsg);
    return false; //form won't submit
  }

  return true; //form will submit
}

As you can see, I also used getFullYear() so that we don't hard code a fixed current year.

But it would probably be cleaner if you use an <input type="date"> element rather than a text box.

Anis R.
  • 6,656
  • 2
  • 15
  • 37
  • No, this is plain javascript. – Anis R. Apr 30 '19 at 21:45
  • 1
    @Luca But like I mentioned in comments, the age calculation could be up to a year out, someone could be 14, or 81 and you will still allow them, is that OK? – Keith Apr 30 '19 at 21:48
  • thats fine but its not working.... it still allows me to submit even if there is an error – Luca Apr 30 '19 at 21:50
  • @Luca oh, okay, there's a way to prevent submitting. I'll edit my answer. – Anis R. Apr 30 '19 at 21:52
  • @Luca did you edit your HTML as well to read `
    ` ?
    – Anis R. Apr 30 '19 at 22:04
  • i am not allowed to have javascript in my html page.. if you give me 1 sec i will update your code and above and show you what i have – Luca Apr 30 '19 at 22:06
  • @AnisR. i have edited your code can you take a look? – Luca Apr 30 '19 at 22:08
  • @Luca I edited my answer, and tested it. It should work fine now. – Anis R. Apr 30 '19 at 22:20
  • @AnisR. With HTML5 (released in 2014) there are [better ways](https://developer.mozilla.org/en-US/docs/Learn/HTML/Forms/Form_validation) to report the error to the user instead of using `alert()`. You can read more at – some May 01 '19 at 00:18
2

document.getElementById("DOB").value is a string, not a date, so you need to convert it. For that there are different methods; one is to convert the string to YYYY-MM-DD format and pass that to the Date constructor.

Moreover, someone's age changes on their birthday, not at the change of a calendar year, so you need a different logic to get their age. One way is to precalculate the date of 15 years ago and of 81 years ago, and test that the entered birthdate lies between these two extremes.

var DOB = document.getElementById("DOB");
var output = document.getElementById("output");
var go = document.getElementById("go");

var fifteenYearsAgo = new Date();
fifteenYearsAgo.setFullYear(fifteenYearsAgo.getFullYear() - 15);
var eightyOneYearsAgo = new Date();
eightyOneYearsAgo.setFullYear(eightyOneYearsAgo.getFullYear() - 81);

// Function returns true when age is OK, false otherwise
function check() {
    var birthDate = new Date(DOB.value.replace(/(..)\/(..)\/(....)/, "$3-$2-$1"));
    return birthDate <= fifteenYearsAgo && birthDate > eightyOneYearsAgo;
}

go.addEventListener("click", function() {
    if (check()) {
        output.textContent = "Your age is OK";
    } else {
        output.textContent = "Your age must be between 15 and 80";
    }
});
Birthdate: <input id="DOB"><button id="go">Go</button>
<div id="output"></div>

HTML5

If you are certain about your clients having HTML5 support, then use type="date" for your input element, and dynamically set the min and max attributes of a date typed input element and rely on form validation. If the form gets into the submit handler, you can be sure the validations passed:

var DOB = document.getElementById("DOB");
var form = document.querySelector("form");

var fifteenYearsAgo = new Date();
fifteenYearsAgo.setHours(0, 0, 0, 0);
fifteenYearsAgo.setFullYear(fifteenYearsAgo.getFullYear() - 15);

var eightyOneYearsAgo = new Date();
eightyOneYearsAgo.setHours(0, 0, 0, 0);
eightyOneYearsAgo.setFullYear(eightyOneYearsAgo.getFullYear() - 81);
// Border case: in leap years next condition could be false
if ((new Date()).getDate() === eightyOneYearsAgo.getDate()) { 
    eightyOneYearsAgo.setDate(eightyOneYearsAgo.getDate()+1);
}

DOB.setAttribute("min", eightyOneYearsAgo.toLocaleString("se").slice(0,10));
DOB.setAttribute("max", fifteenYearsAgo.toLocaleString("se").slice(0,10));

form.addEventListener("submit", function(e) {
    alert("Your age is OK");
    e.preventDefault();
    return false;
});

function validationMessage() {
    DOB.setCustomValidity("");
    const msg = DOB.checkValidity() ? ""
              : DOB.validity.valueMissing ? "This field is required"
              : DOB.validity.rangeOverflow ? "You must be at least 15"
              : DOB.validity.rangeUnderflow ? "You must be at most 80"
              : "Enter a valid date"
    DOB.setCustomValidity(msg);
}
DOB.addEventListener("input", validationMessage);
validationMessage();
<form>
  <label>
      Date of birth:
      <input type="date" name="birth date" id="DOB" required="required"/>
  </label>
  <button id="go">Go</button>
</form>
trincot
  • 317,000
  • 35
  • 244
  • 286
  • This is the best answer so far, only thing I would say is make sure `fifteenYearsAgo` is at the start of the day, and `eightyOneYearsAgo` is at the start of the day. Because your birthday doesn't change mid day either. – Keith Apr 30 '19 at 21:55
  • HTML5 was released in 2014, and the question uses features from HTML5 with `required` and `pattern`. HTML5 have support for [form validation](https://developer.mozilla.org/en-US/docs/Learn/HTML/Forms/Form_validation) and custom errors that are displayed at the field without adding a special element fort it. – some May 01 '19 at 00:30
  • Updated answer in light of the above comments. – trincot May 01 '19 at 09:06
0

document.getElementById("DOB").value; will give you something like 10/10/2000 and performing arithmetic operations on this string will result in NaN. That must be causing an issue.

Validating date is a more complex than you imagine. There are a lot of things that you need to consider. Use libraries like moment to help you in validating dates.

Edit: Use moment's Difference method to calculate the age.

mbhargav294
  • 389
  • 1
  • 3
  • 15
  • OP isn't using type="date", using type="text", but the rest of your answer is still relevant – Jaromanda X Apr 30 '19 at 21:33
  • Updated my answer – mbhargav294 Apr 30 '19 at 21:37
  • 3
    Not everything needs a library, while moment is good, it's definitely not worth including for a single calculation – DBS Apr 30 '19 at 21:37
  • 2
    @DBS it is if you want that calculation to be accurate and to account for variables such as leap years and daylight savings ;) – APAD1 Apr 30 '19 at 21:41
  • @APAD1 Don't need a library for that: Create a date object with the first date (`let dob=newDate(year,month-1,date)`), and then create another date (`let minDate=newDate(year+15,month-1,date)`), then you can compare that to todays date. See my answer for details. – some Apr 30 '19 at 23:41
0

You can use built in min and max props for input. Try something like this.

<p>Enter a number and click OK:</p>

<input id="id1" type="number" min="15" max="80" required>
<button onclick="myFunction()">OK</button>

<p>If the age is less than 15 or greater than 80, an error message will be 
displayed.</p>

 <p id="demo"></p>

  <script>
function myFunction() {
 var inpObj = document.getElementById("id1");
 if (!inpObj.checkValidity()) {
  document.getElementById("demo").innerHTML = inpObj.validationMessage;
 } else {
 document.getElementById("demo").innerHTML = "Input OK";
 } 
} 
</script>

Theoretically this should work.

  • it needs to be in dd/mm/yyyy format otherwise i would have already done this – Luca Apr 30 '19 at 21:40
  • Then i would suggest to use the built in function .getFullYear() as answered above. or if you really wanna get precise you can look into new date() . Check out this documentation. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date –  Apr 30 '19 at 21:47
0

Since you are using pattern and required I assume that you want the error message (if the age is out of range) to be shown to the user in the same way as if the entered date is in the wrong format or is missing. That can be achieved with setCustomValidity.

If you add an event listener of the input event on the DOB-element, you can run a function that checks if the entered age is in rage. It will set the custom error message if the age is out of range, or if the entered date is invalid. Otherwise it let the browser handle the error (if it is missing or of wrong pattern).

function validateDOB(event) {
  const minAge = 15, maxAge = 80;

  // No custom error message. The broswer will complain if the input isn't in the
  // correct form, or if the value is missing since the element has "pattern" and
  // and "required".
  this.setCustomValidity('');
  
  // Check if there are any other errors
  if ( !this.validity.valid ) return;

  // Check format of input, and split it into parts
  const dobArrayText = this.value.trim().match(/^(\d{1,2})\/(\d{1,2})\/(\d{4})$/);
  // dobArrayText is null if not in correct format. Let the broswer handle the error.
  if (!dobArrayText) return;

  // Decode dobArrayText to numeric values that can be used by the Date constructor.
  const dob = {
    year : +dobArrayText[3],
    month : (+dobArrayText[2]) - 1, // month is zero based in date object.
    day : +dobArrayText[1]
  }
  const dobDate = new Date( dob.year, dob.month, dob.day );
  // Check validity of date. The date object will accept 2000-99-99 as input and
  // adjust the date to 2008-07-08. To prevent that, and make sure the entered
  // dobDate is a valid date, I check if the entered date is the same as the parsed date.
  if (
    !dobDate
    || dob.year !== dobDate.getFullYear()
    || dob.month !== dobDate.getMonth()
    || dob.day != dobDate.getDate()
  ) {
    this.setCustomValidity('Invalid date');
    return;
  }
  // Calc minAgeDate and maxAgeDate
  const minAgeDate = new Date(dob.year + minAge, dob.month, dob.day);
  const maxAgeDate = new Date(dob.year + maxAge, dob.month, dob.day);
  // Get todays date and set Hours, Minutes, Seconds and Milliseconds to 0.
  const todayTimestamp = new Date().setHours(0,0,0,0);
  // Check validity and set a custom error message if needed.
  if ( todayTimestamp < minAgeDate ) {
    this.setCustomValidity(`Sorry, you must be older than ${minAge} years old`);
  }
  else if ( todayTimestamp >= maxAgeDate ) {
    this.setCustomValidity(`Sorry, you must be younger than ${maxAge} years old`);
  }
}

function formInit() {
  document.getElementById('DOB').addEventListener("input", validateDOB);
}

window.addEventListener('DOMContentLoaded', formInit);
<form id="myForm">
  <label>
      Date of birth:
      <input type="text" name="birth_date" id="DOB"
             placeholder="dd/mm/yyyy" maxlength="10" pattern="\d{1,2}\/\d{1,2}\/\d{4}"
             required="required"/>
  </label>

  <button type="submit">Submit</button>
</form>
some
  • 48,070
  • 14
  • 77
  • 93