Run custom validation script when form is submitted

156 Views Asked by At

I have an ASP.NET Core Razor Pages application with a page that requires some custom validation. I want this validation to run on the client using custom JavaScript.

How can I ensure my validation script runs when the form is submitted? It also needs to run if $form.validate() and $form.valid() are called manually.

Googling around, I found a few examples. But they seem very old and use technologies such as WebForms.

Can someone offer some suggestions or refer me to resources that cover this issue in detail?

NOTE: My validation will check that a value is provided for at least one of a group of input elements. So, if possible, I just want my new validation to run and not be associated with any one input.

UPDATE

Based on information I found on the Web, I came up with the following.

$.validator.addMethod("validGroups", function (value, element, params) {
    alert('Test');
    return false;
}, 'Error Message');

jQuery.validator.unobtrusive.adapters.add('validGroups', function (options) {
    options.rules['validGroups'] = {};
    options.messages['validGroups'] = options.message;
});

But I tried a number of variations on this but none of them resulted in this validator being run.

1

There are 1 best solutions below

7
VonC On BEST ANSWER

You want your custom validation to work within the existing infrastructure of an ASP.NET Core Razor Pages application, and to specifically take care of the situation where built-in annotations are not enough.

You would need to make sure the custom validation integrates seamlessly with jQuery Validation and jQuery Unobtrusive Validation used by ASP.NET Core.
The idea is to add custom methods to the jQuery Validator object and integrating them with the unobtrusive validation framework, which is a practical application of extending the client-side validation capabilities discussed in the documentation "Model validation in ASP.NET Core MVC and Razor Pages".

You have already started this by using $.validator.addMethod (Custom client-side validation). But since it needs to run as part of the existing validation infrastructure, you must tie this custom validation to a form element or trigger it manually as needed.

To make sure your custom validation runs both when the form is submitted and when $form.validate() and $form.valid() are called, you can bind it to the form's submit event and also manually trigger it as part of these methods if necessary. Since you mentioned your validation does not associate with any one input, you might need to manually trigger this validation or make sure it is checked as part of the form's overall validation process.

$(function() {
    // Define the custom validation method
    $.validator.addMethod("validGroups", function(value, element, params) {
        // Your custom validation logic here.
        // Return true if validation passes, false otherwise.
        // For example, check if at least one input in a group has a value
        var isValid = false;
        $(params).each(function() {
            if (this.value) {
                isValid = true;
                return false; // break out of loop
            }
        });
        return isValid;
    }, 'At least one field must be filled.');

    // Add the custom method to the validator
    jQuery.validator.unobtrusive.adapters.add('validGroups', function(options) {
        options.rules['validGroups'] = '.input-group-class'; // Use a selector that matches your group of inputs
        options.messages['validGroups'] = options.message;
    });

    // Make sure the form uses validation
    var $form = $("#yourFormId"); // Replace with your form's ID
    $form.validate({
        // Additional validation options if needed
    });

    // Optional: Bind to form submit to make sure custom validation is considered
    $form.on("submit", function(event) {
        if (!$form.valid()) {
            event.preventDefault(); // Prevent form submission if validation fails
        }
    });
});

Compared to your original script, this one does define how to select the group of inputs that should be validated together. It uses a selector (.input-group-class in the example) to specify which inputs are part of the validation rule. That should clarify how to target multiple inputs for a single validation rule, which is important in your scenario (checking that at least one of a group of inputs is provided).

The code includes an optional step to bind the custom validation to the form's submit event. That way, the custom validation logic is considered before the form is submitted, preventing submission if the validation fails. That is a direct way to make sure custom validations are enforced alongside the built-in validations.

You did not explicitly show how to trigger or make sure this validation is checked alongside the built-in methods. The new code shows the integration of the custom validation so that it works with manual calls to $form.validate() and $form.valid() as well.


Neither my jQuery.validator.addMethod nor jQuery.validator.unobtrusive.adapters.add code is getting called.
Currently, I'm validating my code by calling validate() and valid(), but I want it to also work if the form is submitted by user action. I just want my code to run when the regular validation runs.

I changed the options.rules['validGroups'] to .input for now. (My final code will be too complex to use classes. I will need to generate a custom script from C#.) I'll probably just have to manually call my code.

Make sure jQuery Validation and jQuery Unobtrusive Validation scripts are correctly referenced in your page. These scripts must be loaded for the custom validation to integrate with the ASP.NET Core validation lifecycle.

If the $.validator.addMethod and jQuery.validator.unobtrusive.adapters.add methods are not being called, verify that these scripts are placed where they are guaranteed to run after the jQuery and validation scripts have loaded. It is common to place these in a script tag at the bottom of the page or within a $(document).ready() function to make sure all dependencies are loaded first (as in this answer).

Since your custom validation logic must run as part of the form's standard validation process, make sure you are not inadvertently bypassing the framework's validation mechanism. If you are manually invoking validate() and valid() without seeing your custom validation logic run, there might be an issue with how or when these methods are being called relative to your custom validation setup.

If your validation logic is complex and dynamically generated from C#, you might opt to inject these rules directly into your page as part of your Razor view. That can be achieved by rendering a script block containing the custom validation logic and rules, tailored to the specific needs of the form being rendered.

To make sure your custom validation logic is executed alongside the standard validation process, consider explicitly invoking this logic as part of the form's submit event. That can be done by attaching an event listener to the form's submit event, which first runs your custom validation logic and only proceeds with the submission if the custom validation passes.

$(document).ready(function() {
    var $form = $("#yourFormId"); // Replace with your form's ID
    $form.on('submit', function(e) {
        if (!customValidationLogic()) { // Replace `customValidationLogic` with your method
            e.preventDefault(); // Prevent form submission
            // Optionally, display an error message or highlight invalid fields
        }
    });

    function customValidationLogic() {
        // Implement your custom validation logic here
        // Return `true` if validation passes, `false` otherwise
    }
});

If you are manually triggering validation checks, make sure they complement the unobtrusive validation process rather than conflict with it. That might involve manually adding or removing error messages in a manner consistent with how unobtrusive validation displays its messages.