Search code examples
jqueryasp.net-mvc-4jquery-validateunobtrusive-validation

jQuery validate only validates once when changing select option


I have a pair of dependent fields - state and zipcode, and an api controller that validates that a zip code appears in a state. I can cause a change to the State dropdown to validate the zipcode again just fine - however, afterwards if I change the select back, the validation does not occur!

The part of the page that is important:

@Html.LabelFor(model => model.State, new { @class = "control-label col-md-1" })
<div class="col-md-2">
    @Html.DropDownListFor(model => model.State, Model.StateSelections, new { htmlAttributes = new { @class = "form-control" } })
    @Html.ValidationMessageFor(model => model.State, "", new { @class = "text-danger" })
</div>

@Html.LabelFor(model => model.Zip, new { @class = "col-md-1 control-label" })
<div class="col-md-2">
    @Html.EditorFor(model => model.Zip, new { htmlAttributes = new { @class = "form-control" } })
    @Html.ValidationMessageFor(model => model.Zip, "", new { @class = "text-danger" })
</div>

The jquery:

$(document).ready(function () {

    $("#@Html.IdFor(model => model.State)").on("change", function () {
        $("#@Html.IdFor(model => model.Zip)").valid();
    });


    $("#@Html.IdFor(model => model.Zip)").rules("add", {
        "remote": {
            url: zipcodeApiUrl,
            type: "GET",
            data: {
                stateAbbreviation: function () {
                    //alert('I validate, but only the first time');
                    return $("#@Html.IdFor(model => model.State)").val();
                }
            }
        }
    });
});

Here is the rendered code:

var stateId = '#State';
var zipcodeId = '#Zip';
$(document).ready(function () {

    $(stateId).on("change", function () {
        $(zipcodeId).valid();
    });


    $(zipcodeId).rules("add", {
        "remote": {
            url: zipcodeApiUrl,
            type: "GET",
            data: {
                stateAbbreviation: function () {
                    return $(stateId).val();
                }
            }
        }
    });

});

(snip)

<label class="control-label col-md-1" for="State">State</label>
<div class="col-md-2">
    <select data-val="true" data-val-required="The State field is required." htmlAttributes="{ class = form-control }" id="State" name="State">
        <option value="AK">AK - ALASKA</option>
        <option value="AL">AL - ALABAMA</option>
        <option value="AP">AP - ARMED FORCES PACIFIC</option>
        (...)
        <option value="WI">WI - WISCONSIN</option>
        <option value="WV">WV - WEST VIRGINIA</option>
        <option value="WY">WY - WYOMING</option>
        </select>
    <span class="field-validation-valid text-danger" data-valmsg-for="State" data-valmsg-replace="true"></span>
</div>

<label class="col-md-1 control-label" for="Zip">Zip</label>
<div class="col-md-2">
    <input class="form-control text-box single-line" data-val="true" data-val-length="The field Zip must be a string with a maximum length of 5." data-val-length-max="5" data-val-regex="Zip code must be a 5 digit number" data-val-regex-pattern="\d{1,5}" data-val-required="The Zip field is required." id="Zip" name="Zip" type="text" value="11735" />
    <span class="field-validation-valid text-danger" data-valmsg-for="Zip" data-valmsg-replace="true"></span>
</div>

Edit: Weirdly enough, if I delete a character in the zipcode field, validation starts working again until I interact with the dropdown. Maybe there's a data attribute that needs to be changed in order to call valid on it again?

Trying to figure out why valid() only works once.


Solution

  • I dug in pretty far and found the exact LoC that were causing the issue and posted to the repo. It seems that it's actually intended to perform that way!

    http://github.com/jzaefferer/jquery-validation/issues/1567

    I got a pull request merged into jquery-validate that fixes this bug!