Search code examples
asp.net-mvcunobtrusive-validation

jQuery Validate is working with ASP.NET MVC Partial View but not Editor Templates


I have a EditorTemplate PatientProfile View that gets passed in a sub model with 2 fields for the 2 input. I am trying to then use jQuery validate to validate those 2 input fields but it is not working.

However when I try and create that exact View as a Partial View, i.e. having the exact PatientProfile View under the Shared folder then invoking it using

@Html.Partial("PatientProfile", Model.PatientProfile)

then the validation works.

Form.cshtml View that call to render the PatientProfile View

@model Test.Models.FormGroup1

@{
    ViewBag.Title = "FormGroup1";
    Layout = "~/Views/Shared/_ContainerLayout.cshtml";
}

@Html.Partial("PatientProfile", Model.PatientProfile)   @* Validation Works *@

@Html.EditorFor(m => m.PatientProfile)                  @* Renders but validation does not work *@

PatientProfile.chstml View

@model Test.Models.PatientProfile

<form id="PatientProfile" class="form-horizontal" action="@Url.Action("PatientProfile", "Form")" method="post" autocomplete="off">
    <div class="row">
        <div class="col-md-6">
            <div class="form-group row">
                <label class="col-md-2 col-sm-2 col-form-label control-label">Firstname</label>
                <div class="col-md-10 col-sm-10 validateInput">
                    @Html.TextBoxFor(model => model.Firstname.Value, new { @class = "form-control", placeholder = "", tabindex = "2" })
                    @Html.ValidationMessageFor(model => model.Firstname.Value, "", new { @class = "text-danger" })
                </div>
            </div>
        </div>
        <div class="col-md-6">
            <div class="form-group row">
                <label class="col-md-2 col-md-2 col-sm-2 col-form-label control-label">Lastname</label>
                <div class="col-md-10 col-sm-10 validateInput">
                    @Html.TextBoxFor(model => model.Lastname.Value, new { @class = "form-control", placeholder = "", tabindex = "3" })
                    @Html.ValidationMessageFor(model => model.Lastname.Value, "", new { @class = "text-danger" })
                </div>
            </div>
        </div>
    </div>
</form>

<script>
    $(document).ready(function () {
        $("#PatientProfile").validate({
            onfocusout: function (element) { 
                $(element).valid();
            },

            rules: {
                "Firstname.Value": { required: true },
                "Lastname.Value": { required: true },
            },
            errorElement: "em",
            errorPlacement: function (error, element) {
                error.addClass("help-block");

                if (element.prop("type") === "checkbox") {
                    error.insertAfter(element.parent("label"));
                } else {
                    error.insertAfter(element);
                }
            },
            highlight: function (element, errorClass, validClass) {
                $(element).parents(".validateInput").addClass("has-error").removeClass("has-success");
            },
            unhighlight: function (element, errorClass, validClass) {
                $(element).parents(".validateInput").removeClass("has-error");
            },
        });
    });
</script>

How can I get the Validation to work with EditorFor(m => m.PatientProfile)? I need it to work with EditorFor because the fields will need to be updated/edited which I don't think I can use Partial Views, please correct me if I am wrong.


Solution

  • If you use your browsers inspection tool to look at the input fields, you'll probably find they have a different name to what you expected.

    In editor templates the holding property is set as a prefix, so from memory, they will look something like

    PatientProfile.FirstName.Value
    

    If you want to change that, in your editorTemplate, you can do

    @model Test.Models.PatientProfile
    @{
        ViewData.TemplateInfo.HtmlFieldPrefix = string.Empty;
    }
    

    That will remove the PatientProfile from the field names