JQuery Validate with dynamically generated forms

JQuery Validate with dynamically generated forms

Recently, I worked on a project that required validating forms client-side that were served via an Ajax call to the server.

When a dropdown changes, the UI triggers a request for a dynamically generated form. It sends an ID to the server and expects a fully formed HTML form back. This HTML is then added to the DOM, replacing the existing form.

The code snippets below have been simplified to keep the examples concise.

Controller action

[HttpPost]
public ActionResult GetForm(int formId)
{
    return _formRepository.GetFormHtml(formId);
}

This action will generate the HTML for the form, along with all the correct data attributes required to validate the form with jQuery Validate.

Ajax call

var postData = {
    formId: 12
};

$.post("/Home/GetForm", postData, function (data) {
    $("#dynamicFormContainer").html(data);
});

At this point, the new form is displayed but jQuery Validate is not firing and no client-side validation is performed.

After a fair bit of Googling, I found the answer to ensure that jQuery Validate kicks in and correctly validates the newly added form. The plugin's documentation is, unfortunately, rather lacking...

Parse form

function reinitialiseFormValidation(elementSelector) {
    var validator = $(elementSelector).validate();
    validator.destroy();
    $.validator.unobtrusive.parse(elementSelector);
};

This function accepts the form selector as a parameter, destroys the currently initialised validator object, and then parses the new form. This parsing tells the jQuery Validator to analyse the form, read the data attributes in the HTML, and build the set of rules it requires.

It is important to destroy the current validator, as without this parsing, nothing is done because the old form's rules are still being applied.

We now need to invoke our function inside the success callback of our Ajax call.

$.post("/Home/GetForm", postData, function (data) {
    $("#dynamicFormContainer").html(data);
    reinitialiseFormValidation("#dynamicForm");
});

Now we have our dynamically generated form correctly validating client-side.