views:

1238

answers:

3

I have an HTML page with a web form. Among other things, it includes the following form fields:

  • Title - textbox
  • SourceName - textbox
  • Url - textbox
  • FullText - textbox
  • PublicationDate - textbox using jQuery datepicker UI
  • StartDate - textbox using jQuery datepicker UI
  • EndDate - textbox using jQuery datepicker UI

I am trying to implement the jQuery validator multiple field sample:

jQuery(document).ready(function() {
// a custom method for validating the date range
jQuery.validator.addMethod("dateRange", function() {
    var date1 = new Date(jQuery("#StartDate").val());
    var date2 = new Date(jQuery("#EndDate").val());
    return (date1 < date2);
}, "Please check your dates. The start date must be before the end date.");

// a new class rule to group all three methods
jQuery.validator.addClassRules({
    requiredDateRange: { required: true, date: true, dateRange: true }
});

// overwrite default messages
jQuery.extend(jQuery.validator.messages, {
    required: "These fields are required",
    date: "Please specify valid dates"
});

jQuery("#mainForm").validate({ 
    submitHandler: function() {
        alert("Valid date range.")
    },
    groups: {
        dateRange: "StartDate EndDate"
    },
    rules: {
        "Title": "required",
        "SourceName": "required",
        "Url": "required",
        "FullText": "required",
        "PublicationDate": "required",
        "CategoryCount": {required: true, min: 1}
    },
    messages: {
        "Title": "Please type in a headline.",
        "SourceName": "Please select a source by typing a few letters and selecting from the choices that pop up.",
        "Url": "Please paste or type in a web page link.",
        "FullText": "Please paste in the full text of the source report.",
        "PublicationDate": "Please provide a date of publication.",
        "CategoryCount": "Please specify at least one category."
    }
});

// Capture changes to the list of selected categories by 
// storing the count in a hidden field.
jQuery(".categoryCheckbox").click(function() {
        var count = new Number(jQuery("#CategoryCount").val());
        if (jQuery(this).attr("checked") == true) {
            count = count + 1;
        } else {
            count = count - 1;
        }

        if (count < 0) {
            count = 0
        };

        jQuery("#CategoryCount").val(count);
});

});

It validates all but the date range. I tried doing this a little more custom, but explicitly creating the Date objects prior to the return statement (in the demo, it's all on one line), but this did no good. Does anyone have experience making this actually work?

EDIT: I added a line to pop up an alert message when the dateRange method is called, but it never shows up. I wonder if the groups and rules parts of the validator just don't work together.

+1  A: 

Have you checked that the values of date1 and date2 are actually getting set? Are you calling

$("#StartDate").datepicker();
$("#EndDate").datepicker();

to actually create the datepickers?

How about the html? The example you point to had the ids and names of the edit boxes set (I don't know if the validator uses the id or the name but it could be either from that sample).

Rob Russell
Both id and name attributes for all fields are the same.The datepicker is initialized on the CSS class. This works because in a browser I test using the datepicker's UI to set the dates.
Tim Rourke
Your response prompted me to go back to add an alert call in the validator.addMethod("dateRange") call. The alert never shows up, so I assume the method is never being called by the validator.
Tim Rourke
A: 

After trying several wild variations based on the documentation, I found that this method just doesn't work the way it is shown in the sample. Here is what I found I had to do. I added a rule for the EndDate field and had it call the function dateRange. Only then did the dateRange function fire.

The resulting script is much clearer, I think, making me suspect the sample I saw was outdated.

jQuery(document).ready(function() {
    // a custom method for validating the date range
    jQuery.validator.addMethod("dateRange", function() {
        var date1 = new Date(jQuery("#StartDate").val());
        var date2 = new Date(jQuery("#EndDate").val());
        return (date1 < date2);
    }, "Please check your dates. The start date must be before the end date.");

    jQuery("#mainForm").validate({
        rules: {
            "Title": "required",
            "SourceName": "required",
            "Url": "required",
            "FullText": "required",
            "PublicationDate": "required",
            "SourceName": "required",
            "CategoryCount": { required: true, min: 1 },
            "EndDate": { required: true, date: true, dateRange: true }
        },
        messages: {
            "Title": "Please type in a headline.",
            "SourceName": "Please select a source by typing a few letters and selecting from the choices that pop up.",
            "Url": "Please paste or type in a web page link.",
            "FullText": "Please paste in the full text of the source report.",
            "PublicationDate": "Please provide a date of publication.",
            "SourceName": "Please select a source for this report.<br />",
            "CategoryCount": "Please specify at least one category.",
            "EndDate": "Please check your dates. The start date must be before the end date."
        }
    });

    // Capture changes to the list of selected categories by 
    // storing the count in a hidden field.
    jQuery(".categoryCheckbox").click(function() {
        var count = new Number(jQuery("#CategoryCount").val());
        if (jQuery(this).attr("checked") == true) {
            count = count + 1;
        } else {
            count = count - 1;
        }

        if (count < 0) {
            count = 0
        };

        jQuery("#CategoryCount").val(count);
    });
});
Tim Rourke
+1  A: 

This works for me to assure that the selected date isn't before the current date:

$.validator.addMethod("dateRange", function() {
    var today = new Date();
    var event_date = new Date( $('#event_date').val() );
    if( event_date >= today )
        return true;
    return false;
}, "Please specify a correct date:");

and:

     rules: {
        event_date: { required: true, dateRange: "event_date" },
    },
J. LaRosee
Yes, that's essentially what I did in my answer to my own question. The difference in my case was that I needed to check two dates, and if both were non-null, ensure that the end date was later than the start.
Tim Rourke