Search code examples
jqueryasp.netasp.net-mvcunobtrusive-validation

jQuery Validate allowing invalid field to submit


I've got an ASP.NET MVC form that is using jQuery Validate to perform validation. All fields validate just fine except for the last one called 'AmtRemaining'. This field has an initial value, but this value changes based on the value input of two other fields ('AmtAdministered' & 'AmtWasted'). Validation on this field is to ensure that the value does not go below zero (using the min: 0 method in jQuery Validate).

Now, if I tab to the "AmtRemaining" field and then tab off of it, it appears the validation works. If the value is below zero, it will give me an error message, however, when I go to submit the form, it allows the form to submit even though the field fails validation. And its only for this field. All of the other fields, if invalid, will cause the form not to submit. Really strange.

Here is my jQuery used for validation:

<script type="text/javascript">
    $(document).ready(function () {
        $('#DrugAdministerForm').validate({
            errorClass: 'errorText',
            rules: {
                    AdministeredByAutoComplete: {
                            required: true
                        },
                    AmtAdministered: {
                            required: true,
                            range: [0, 100000]
                        },
                    AmtWasted: {
                            range: [0, 100000]
                        },
                    WitnessAutoComplete: {
                            required: {
                                depends: function (element) {
                                    return ($('#AmtWasted').val() != "" &&
                                            $('#AmtWasted').val() != "0");
                                }
                            }
                        },
                    ProviderList: {
                            required:  true
                        },
                    AmtRemaining: {
                            min: 0                              
                        }
                },
            messages: {
                    AmtAdministered: {
                            required: "Required",
                            range: "Not a valid amount"
                        },
                    AmtWasted: {
                            range:  "Not a valid amount"
                        },
                    WitnessAutoComplete:{
                            required: "Required if waste"
                        },
                    AmtRemaining: {
                            min: "Must be greater than 0"
                        }
                }
                });
    });

</script>

This script is used to calculate the value of "AmtRemaining" based on the input values of "AmtAdministered" and "AmtWasted":

<script type="text/javascript">
    $(document).ready(function () {
        $('#AmtAdministered, #AmtWasted').blur(function () {
            var amtadmin = $('#AmtAdministered').val()
            var waste = $('#AmtWasted').val();
            var remaining = $('#InitialAmtRemaining').val();

            if (!waste)
            {
                waste = 0;
            }

            var tmp = (parseFloat(amtadmin) + parseFloat(waste));
            var result = (remaining - tmp);

            $('#AmtRemaining').val(result);
        });
    });

</script>

And this is the code for the View, if anyone is interested

@using (Html.BeginForm("Add", "Patient", FormMethod.Post, new { id = "DrugAdministerForm" }))
{
    <br />
    <table class="Tbl">
        <tr>
            <td class="right">Lot #:  </td>
            <td class="left">@Html.TextBox("LotNumberReadOnly", @Model.SelectedLot.LotNumber, new { @readonly = "readonly", @class = "TxtBoxGray" })</td>
        </tr>
        <tr>
            <td class="right">Drug Name/Type:  </td>
            <td class="left">
                @Html.TextBox("DrugNameReadOnly", @Model.SelectedLot.DrugName, new { @readonly = "readonly", @class = "TxtBoxGray", @style = "width:400px" })
                @Html.Hidden("DrugEntryCodeHidden", @Model.SelectedLot.DrugEntryCode)
            </td>
        </tr>
        <tr>
            <td class="right">Site:</td>
            <td class="left">
                @Html.TextBox("SiteNameReadOnly", @Model.SelectedLot.SiteName, new { @readonly = "readonly", @class = "TxtBoxGray", @style = "width:400px" })
                @Html.Hidden("SiteNumberHidden", @Model.SelectedLot.SiteNumber)
            </td>
        </tr>
        <tr>
            <td class="right">Patient MRN:  </td>
            <td class="left">@Html.TextBox("PatientMrnReadOnly", @Model.Patient.Mrn, new { @readonly = "readonly", @class = "TxtBoxGray" })</td>
        </tr>
        <tr>
            <td class="right">Patient Name:  </td>
            <td class="left">@Html.TextBox("PatientNameReadOnly", @Model.Patient.FullNameLastNameFirst, new { @readonly = "readonly", @class = "TxtBoxGray" })</td>
        </tr>
        <tr>
            <td class="right">Date of Birth:  </td>
            <td class="left">@Html.TextBox("PatientDobReadOnly", @Model.Patient.DateOfBirth, new { @readonly = "readonly", @class = "TxtBoxGray" }) </td>
        </tr>
        <tr>
            <td class="right">Provider:  </td>
            <td class="left">@Html.DropDownList("ProviderList", "Choose...")</td>
        </tr>
        <tr>
            <td class="right">Administered By:  </td>
            <td class="left">@(Html.Kendo().AutoComplete().Name("AdministeredByAutoComplete").DataTextField("UserName").BindTo(Model.UserNames).Filter("contains")
                                            .HtmlAttributes(new { value = (string)ViewBag.LoggedInUserName, 
                                            style = "padding:0px; font-size:10pt; border-radius:0; color:#000; line-height:1em;" }))</td>
        </tr>
        <tr>
            <td class="right">Amount Administered (CCs):  </td>
            <td class="left">@Html.TextBox("AmtAdministered", null, new { @id = "AmtAdministered", @type = "text", @style = "width:30px"})</td>
        </tr>
        <tr>
            <td class="right">Amount Wasted (CCs):  </td>
            <td class="left">@Html.TextBox("AmtWasted", null, new { @style = "width:30px"})</td>
        </tr>
        <tr>
            <td class="right">Waste Witnessed By:  </td> 
            <td class="left">@(Html.Kendo().AutoComplete().Name("WitnessAutoComplete").DataTextField("UserName").BindTo(Model.UserNames).Filter("contains")
                                            .HtmlAttributes(new { style = "padding:0px; font-size:10pt; border-radius:0; color:#000; line-height:1em;" }))</td>
        </tr>
        <tr>
            <td class="right">Amount Remaining (Lot):  </td>
            <td class="left">@Html.TextBox("AmtRemaining", @Model.SelectedLot.CCsRemaining, new { @style = "width:50px", @readonly = "readonly", @class = "TxtBoxGray" })</td>
        </tr>
        <tr>
            <td class="right">@Html.Hidden("InitialAmtRemaining", @Model.SelectedLot.CCsRemaining)</td>
            <td class="left"><input type="submit" value="Record" /></td>
        </tr>
    </table>

}

Anyone have any ideas as to why the form is allowed to submit with an invalid field?


Solution

  • It appears that the AmtRemaining field is marked as readonly. I have seen a number of systems that skip validation of readonly since it is assumed that they won't change.

    Perhaps you could put an onChange method on the other fields to reject changes where the value of AmtRemaining goes below zero.