Question

I have an ajax form on a partial view which uses a custom unobtrusive validator for an either/or style validator (described here). My custom validator works fine when used on a form which is not loaded via an ajax call. This partial however, is loaded via an @Ajax.ActionLink call which loads the partial into the containing view.

Containing view:

<div id="form-container">
    @Html.Action("Login", "MyController") //Initial state. Loads Login.cshtml partial view
</div>

Login.cshtml partial:

//contains markup for login form fields, but also this link to the signup partial (Signup.cshtml) 
@Ajax.ActionLink("click here", "Signup", "MyController", 
    new AjaxOptions
    {
        OnSuccess = "initializeValidation();", 
        InsertionMode = InsertionMode.Replace, 
        UpdateTargetId = "form-container"
    })

Signup.cshtml partial:

@model SignupViewModel
<div>
    @using (Ajax.BeginForm("Signup", "MyController", new AjaxOptions
                            {
                                OnSuccess = "initializeValidation();",
                                InsertionMode = InsertionMode.Replace, 
                                UpdateTargetId = "form-container"
                            }))
    {
    <p>
        @Html.LabelFor(m=>m.Username)
        @Html.EditorFor(m=>m.Username)
        @Html.ValidationMessageFor(m=>m.Username)
    </p>
    <p>               
        @Html.LabelFor(m=>m.Email)
        @Html.EditorFor(m=>m.Email)
        @Html.ValidationMessageFor(m=>m.Email)
    </p>        
    <input type="submit" value="Next"/>
    }
</div>

My javascript method initializeValidation() has the following code to reset the unobtrusive validation:

$('form').removeData("validator");
$('form').removeData("unobtrusiveValidation");
$.validator.unobtrusive.parse('form');

The problem I have is that the custom validator does not work on a form which is loaded via @Ajax.ActionLink. I looked at this question and this question which correctly reset the standard unobtrusive validation methods, but I can't figure out how to reset the custom one. The custom validation method and its unobtrusive adapter is configured with the code below

$.validator.addMethod("eitherorrequired", function (value, element, params) {
    var otherValue = $(params).val();
    return value != "" || otherValue != "";
});
$.validator.unobtrusive.adapters.add("eitherorrequired", ["dependentproperty"], function (options) {
    options.rules["eitherorrequired"] = "#" + options.params.dependentproperty;
    options.messages["eitherorrequired"] = options.message;
});

I've tried including this within the initializeValidation() method, but it still does not work.

Was it helpful?

Solution

It turned out that the custom validator method I had did not account for the fact that my input elements had names with underscores in them (due to the fact that my view model class had a property exposing another object containing the properties representing the form fields).

My view model is something like this:

public class MyViewModel
{
    public Info Step1 { get; set; }

    public class Info
    {
         public string Property1 { get; set; }

         [EitherOrRequired(DependentProperty="Property1")]
         public string Property2 { get; set; }
    }
}

Which produces input elements with ids of Step1_Property1 and Step1_Property2. The problem is that the Step1_Property2 input has its data-val-dependentproperty set to "Property1" (the value of the attribute in the view model), so the custom validator method looks for a dependent property which doesn't exist. To overcome this, I modified the custom validator function to ensure that the dependent property has the same prefix as the current property.

$.validator.addMethod("eitherorrequired", function(value, element, params) {
    var name = $(element).attr('name').replace('#', '');
    var i = name.lastIndexOf('.');
    if (i > -1) {
        params = '#' + name.substr(0, i).replace('.', '_') + '_' + params.replace('#', '');
    }
    var otherValue = $(params).val();
    return value != "" || otherValue != "";
});
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top