For some context, the DOM Hierarchy:
Layout.cshtml
> View
> Partial View
The Layout file contains:
<head>
@Scripts.Render("~/bundles/jquery")
@Scripts.Render("~/bundles/jqueryui")
</head>
<body>
<div>
@RenderBody()
</div>
@RenderSection("scripts", required: false)
</body>
The View contains a form. After submitting the form, an AJAX call returns the partial view which is inserted into the View using $('selector').html(PartialViewResult).
The Partial View contains:
// @Scripts.Render("~/bundles/jquery") // [†]
@using(Ajax.BeginForm(...)
{
// MinRate has the appropriate "lessthanproperty" data-val HTML properties
@Html.EditorFor(x => x.MinRate)
// MaxRate has the appropriate "greaterthanproperty" data-val HTML properties
@Html.EditorFor(x => x.MaxRate)
@Html.ValidationSummary()
<button type="submit">Submit</button>
}
@Scripts.Render("~/bundles/jqueryval")
@Scripts.Render("~/bundles/MapRates")
<script>
$(document).ready(function () {
console.log("CSHTML, ON READY");
});
(function() {
console.log("CSHTML, IIFE");
$.validator.addMethod("lessthanproperty", function (value, element, params) {
return Number(value) < Number($(params).val());
});
$.validator.addMethod("greaterthanproperty", function (value, element, params) {
return Number(value) > Number($(params).val());
});
})();
</script>
MapRates Javascript file contains:
$(document).ready(function () {
console.log("JS, ON READY");
});
(function () {
console.log("JS, IIFE")
$.validator.unobtrusive.adapters.add("lessthanproperty", ["comparisonpropertyname"], function (options) {
options.rules["lessthanproperty"] = "#" + options.params.comparisonpropertyname;
options.messages["lessthanproperty"] = options.message;
});
$.validator.unobtrusive.adapters.add("greaterthanproperty", ["comparisonpropertyname"], function (options) {
options.rules["greaterthanproperty"] = "#" + options.params.comparisonpropertyname;
options.messages["greaterthanproperty"] = options.message;
});
})();
Now...from what I can gather, the above sourcecode should work. When the user interacts with the MinRate or MaxRate fields, client-side validation should cause the ValidationSummary to be updated according to any validation errors encountered. †
However, the above does not work unless I uncomment the jquery library reference, @Scripts.Render("~/bundles/jquery")
at the top of the Partial View, above the Ajax.BeginForm line.
But the jquery script is already included in Layout making this the second time it is loaded and so naturally it breaks some things in another, previously unmentioned partial view. For this reason and for good coding practice, I need to get this validation working without the crutch of referencing the jquery library a second time.
When the unobtrusive validation works, with jquery referenced, the printout statements appear as:
JS, IIFE
CSHTML, IIFE
JS, ON READY
CSHTML, ON READY
When the unobtrusive validation breaks, without jquery referenced, the printout statements appear as:
JS, ON READY
JS, IIFE
CSHTML, ON READY
CSHTML, IIFE
Including the jquery library reference causes the script contents to be loaded in the correct order. Without the library, the validation adapters and methods are not incorporated until after the document is ready which apparently makes the unobtrusive js validation non-functional.
How can I get the validation components to load in the correct order and be functional on the page? Also, can anyone explain why including the jquery reference on the view causes it to work at all? Many thanks in advance for your help!
edit: It occurs to me that it may be pertinent to say that the Partial View is a bootstrap modal. I'm not sure if its being a modal with visibility triggered by a data-toggle could cause any odd behavior with validation binders or not.