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

Load a module to run before dom ready


I can't figure out how to load the jQuery, jQueryValidate and jQueryValidateUnobtrusive using require.js with custom validation rules in such a way that the module runs before the dom ready. The custom rules are written as modules (e.g. someCustomValidator.js). The way jQueryValidateUnobtrusive works is that the someCustomValidator should be run after jQuery, jQueryValidate and jQueryValidateUnobtrusive have been loaded but before $.ready is fired. First condition is easy, the module someCustomValidator depends on jQuery, jQueryValidate and jQueryValidateUnobtrusive. It is the second part that I am stuck at. The app.js is loaded just before the closing body tag and so in most of the cases by the time the someCustomValidator are loaded and run, the domReady has already fired. How do I setup the dependencies to satisfy the requirement of someCustomValidator should be run after jQuery, jQueryValidate and jQueryValidateUnobtrusive have been loaded but before $.ready is fired. I thought about using holdReady but I am not sure when to call it and in what module.

The actual definitions validatorSetup.js and someCustomValidator.js are not very important but I am including the basic setup below for completeness.

HTML

...
...
<script src="SomePath/RequireJS/require.js"></script>
<script>
require(["app"]);
</script>
</body>
</html>

app.js

require([
        "jquery",
        "someCustomValidator",
        "anotherCustomValidator"
], function ($,
            someCustomValidator,
            anotherCustomValidator) {

    // Validators should be configured before dom ready.
    someCustomValidator.init();
    anotherCustomValidator.init();

    $(function () {
        // Stuff that should run after dom ready
        someModule1.init();
        someModule2.init();
    });
});

validatorSetup.js

define("validatorSetup", ["jquery", "jquery-validate", "jquery-validate-unobtrusive"], (function ($) {
    var validatorSetup = {
        init: function() {
            this.setDefaults();
        },

        setDefaults:function() {
            this.setIgnore();
        },

        setIgnore: function() {
            $.validator.setDefaults({
                ignore: ":hidden, .ignore"
            });
        }
    };

    return validatorSetup;
}));

someCustomValidator.js

define("someCustomValidator", ["validatorSetup", "jquery", "jquery-validate", "jquery-validate-unobtrusive"], (function (validatorSetup, $) {
    var someCustomValidator = {
        init: function () {
            validatorSetup.setIgnore();

            this.setUpValidationRule();
        },

        setUpValidationRule: function () {
            $.validator.unobtrusive.adapters.add(
                "somerule",
                ["someprop", "rule", "ruleparam"],
                function (options) {
                    options.rules["somerule"] = options.params;
                    options.messages["propertydependencyrule"] = options.message;
                }
            );

            $.validator.addMethod(
                "somerule",
                function (value, element, params) {
                    var rule = params.rule;
                    var ruleParams = params.ruleparam;

                    //Some logic

                    return $.validator.methods[rule].call(this, value, element, ruleParams);
                },
                ""
            );
        }
    };

    return someCustomValidator;
}));

Solution

  • I reorganized the dependencies in this way and the dom ready is head until it is released later after the someCustomValidator.js has been loaded.

    app.js

    require(["jquery"], function($) {
        // Hold the domready
        $.holdReady(true);
    
        require([
                "jquery",
                "someCustomValidator",
                "anotherCustomValidator"
        ], function ($,
                    someCustomValidator,
                    anotherCustomValidator) {
    
            // Validators should be configured before dom ready.
            someCustomValidator.init();
            anotherCustomValidator.init();
    
            // The custom validations have been attached.
            // Now it is ok to let the dom ready to fire
            $.holdReady(false);
    
            $(function () {
                // Stuff that should run after dom ready
                someModule1.init();
                someModule2.init();
            });
        });
    });