TL;DR;

Solution

And here is the final solution. simple plugin to jQuery.

(function ($) { 
    $.validator.unobtrusive.addValidation = function (selector) { 
    //get the relevant form 
    var form = $(selector); 
    // delete validator in case someone called form.validate()
    $(form).removeData("validator"); 
    $.validator.unobtrusive.parse(form); 
  }

Usage

On the partial view use

Explanation - Unobtrusive validation in partial view

Unobtrusive validation is a great feature. You can easily bind your server side validation to client side validation provided by JQuery plugin.

Everything is fine but there is a small problem. When working with Partial views with form you need to load unobtrusive validation two times. First on when the main window is loaded and then the second time when the partial view is injected. Why ? Unobtrusive validation attaches special attributes to field on load event, which are used to bind your own rules defined inside the model with rules implementation provided by JQuery library.

When you create a partial view  fields in new form are without those special attributes and so validation is not working.

One of the solution is to load unobtrusive .js file again. It works but you need to load something twice wasting resources.

Let’s find a better solution.

Scenario 1 - dynamic elements

Some googling / binging and I found this post

This solution is ok if you are adding dynamic element to a form with already attached validation attributes .

In my scenario with dynamic data in partial, I am creating new form waiting to be validated. So let’s look at the next solution.

Scenario 2 - new form (in partial view)

After a lot of research  and debugging through the jQuery and MS validation plugin (at least I know in details how unobtrusive validation works ) . I noticed that unobtrusive creates special OnError method and overrides the default one ( which  injects default label ) in the jQuery

Unobtrusive

    function onError(error, inputElement) {  // 'this' is the form element
        var container = $(this).find("[data-valmsg-for='" + inputElement[0].name + "']"),
            replace = $.parseJSON(container.attr("data-valmsg-replace")) !== false;

        container.removeClass("field-validation-valid").addClass("field-validation-error");
        error.data("unobtrusiveContainer", container);

        if (replace) {
            container.empty();
            error.removeClass("input-validation-error").appendTo(container);
        }
        else {
            error.hide();
        }
    }

Creating proxy with onError :

        if (!result) {
            result = {
                options: {  // options structure passed to jQuery Validate's validate() method
                    errorClass: "input-validation-error",
                    errorElement: "span",
                    errorPlacement: $.proxy(onError, form),
                    invalidHandler: $.proxy(onErrors, form),
                    messages: {},
                    rules: {},
                    success: $.proxy(onSuccess, form)
                },
                attachValidation: function () {
                    $form.validate(this.options);
                },
                validate: function () {  // a validation function that is called by unobtrusive Ajax
                    $form.validate();
                    return $form.valid();
                }
            };
            $form.data(data_validation, result);

There is a method “parse” in unobtrusive plugin , which is responsible for creating validation attributes , adapters and also what’s really important errorPlacement adapter. Everything you need. Knowing all of this we can just use this “parse” on the form and everything should work fine.

Well there is a small problem. This won't work because after a bit of analysis,I found that you can create validation rules once (correctly , without reloading whole script file ). Second and Third try won’t do anything. There will be problems with error placement or validation messages won’t show at all.

It seems that cached values are used. And it doesn’t matter if there are two different forms this behavior is global. Developers assumed that page should have only one form.</p? So how to fix this ? Delete validator data.

Share