3

I have 3 fields for date input:

<input type="text" id="passport-doi-1" name="passport-doi-1" placeholder="DD" maxlength="2">
<input type="text" id="passport-doi-2" name="passport-doi-2" placeholder="MM" maxlength="2">
<input type="text" id="passport-doi-3" name="passport-doi-3" placeholder="YYYY" maxlength="4">

How should I validate with jQuery Validate plugin that if date is input, then this is correct?

Looks like I should create groups of fields (to have only one error message) and then custom validation rule. But how it should look like?

Upd. I've tried to do the following, but it doesn't work:

$.validator.addMethod('validDate', function (value, element) {
  var dd = $("#passport-doi-dd").val();
  var mm = $("#passport-doi-mm").val();
  var yyyy = $("#passport-doi-yyyy").val();
  if (dd=="" && mm=="" && yyyy=="") return true;
  try {
    var date = new Date(yyyy,mm-1,dd,0,0,0,0);
    return mm===(date.getMonth()+1) && dd===date.getDate() && yyyy===date.getFullYear();
  }
  catch(er) {
    return false;
  }
}, 'Please use format DD MM YYYY.');

  ...
  rules: {
    "passport-doi-dd": {
      required: false,
      validDate: true,
      range: [1, 31]
    }, 
    "passport-doi-mm": {
      required: false,
      validDate: true,
      range: [1, 12]
    }, 
    "passport-doi-yyyy": {
      required: false,
      validDate: true,
      range: [1990, 2012]
    }
  },
  messages: {
    "passport-doi-dd": "Please use format DD MM YYYY.",
    "passport-doi-mm": "Please use format DD MM YYYY.",
    "passport-doi-yyyy": "Please use format DD MM YYYY."
  }

1 Answer 1

2

You are on the right track-- You need to pass the Date constructor numbers instead of strings (val will return strings). You can also leverage the params argument to your custom rule to make it a bit more extensible (not specific to three fields with specific ids):

$.validator.addMethod("multidate", function (value, element, params) {
  var daySelector = params[0]
      , monthSelector = params[1]
      , yearSelector = params[2]
      , day = parseInt($(daySelector).val(), 10)
      , month = parseInt($(monthSelector).val(), 10)
      , year = parseInt($(yearSelector).val(), 10)
      , date = new Date(year, month, day);

  return (!$(daySelector).val() && !$(monthSelector).val() && !$(yearSelector).val()) || 
    !isNaN(date.getTime());

});


$(document).ready(function () {
  var dateFields = ["#passport-doi-1", "#passport-doi-2", "#passport-doi-3"];
  $("#dateform").validate({
    errorLabelContainer: "#errors",
    groups: {
      date: dateFields.join("")
    },
    rules: {
      "passport-doi-1": {
        multidate: dateFields
      },
      "passport-doi-2": {
        multidate: dateFields
      },
      "passport-doi-3": {
        multidate: dateFields
      }
    },
    messages: {
      "passport-doi-1": {
        multidate: "Please enter a valid date"
      },
      "passport-doi-2": {
        multidate: "Please enter a valid date"
      },
      "passport-doi-3": {
        multidate: "Please enter a valid date"
      }
    }
  });
});

I think the group option is only for grouping error messages (so you still have to define validation rules for each input).

Example: http://jsbin.com/oqawaz/9

Sign up to request clarification or add additional context in comments.

8 Comments

Thanks, it works perfectly. Is there any way to refer to groups instead of dateFields creation and usage?
@LA_: An easy way to do this would be to use the same array in dateFields and in assigning the groups property --see my updated answer.
Hmm, found one bug with this code - if user input day and month, but hasn't input year, then it is treated as valid (since year element is optional), but it shouldn't be - either full date or nothing.
Yes, it is OK now. I've also added range: [1930, 2012] to the year field, otherwise even 1 was accepted.
just now I've noticed that it accepts wrong dates like 33/13/2000. Looks like !isNaN(date.getTime() is incorrect way to verify dates - see stackoverflow.com/questions/10066005/…
|

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.