Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

EditorFor not rendering data validation attributes without BeginForm

In MVC Application, I want to render some parts of form dynamically (which are like PartialView on Controller Side)

In the partial view, i dont have Html.BeginForm() as the form tag is already rendered.

@model Introduction.Models.Human
<div>
    @Html.EditorFor(model => model.MarriageInformation.SpouseDetails)
    <div class="editor-label">
        @Html.LabelFor(model => model.MarriageInformation.DOM)
    </div>
    <div class="editor-field">
        @Html.EditorFor(model => model.MarriageInformation.DOM)
        @Html.ValidationMessageFor(model => model.MarriageInformation.DOM)
    </div>
</div>

Problem I am facing is in this case EditorFor does not return all the data-val-* attributes.

<div>
   <div class="editor-label">
    <label for="MarriageInformation_SpouseDetails_Name">Name</label>
</div>
<div class="editor-field"><input class="text-box single-line" id="MarriageInformation_SpouseDetails_Name" name="MarriageInformation.SpouseDetails.Name" type="text" value="" /> 

Is this by design or I m missing anything here? Is there any work around here?

The option i am thinking is after ajax load - strip the form and inject inner content.

like image 544
Ajay Bhosale Avatar asked Jun 19 '11 06:06

Ajay Bhosale


People also ask

Which property provide similar functionality as string length but does not do client side validation?

MaxLength Attribute not generating client-side validation attributes.

How do you handle validation in MVC?

In code we need to check the IsValid property of the ModelState object. If there is a validation error in any of the input fields then the IsValid property is set to false. If all the fields are satisfied then the IsValid property is set to true. Depending upon the value of the property, we need to write the code.


2 Answers

you're correct in assuming that this is by design. if you check the source you'll see the following:

// Only render attributes if unobtrusive client-side validation is enabled, and then only if we've
// never rendered validation for a field with this name in this form. Also, if there's no form context,
// then we can't render the attributes (we'd have no <form> to attach them to).
public IDictionary<string, object> GetUnobtrusiveValidationAttributes(string name, ModelMetadata metadata)

To fix this we can write an extension method for use in our partial view:

public static class HtmlExtentions
{
    public static void EnablePartialViewValidation(this HtmlHelper helper)
    {
        if (helper.ViewContext.FormContext == null)
        {
            helper.ViewContext.FormContext = new FormContext();
        }
    }
}

And then use it in our partial view:

@model Introduction.Models.Human
@{ Html.EnablePartialViewValidation(); }
<div>
    @Html.EditorFor(model => model.MarriageInformation.SpouseDetails)
    <div class="editor-label">
        @Html.LabelFor(model => model.MarriageInformation.DOM)
    </div>
    <div class="editor-field">
        @Html.EditorFor(model => model.MarriageInformation.DOM)
        @Html.ValidationMessageFor(model => model.MarriageInformation.DOM)
    </div>
</div>

The last step is to handle parsing the new validation attributes in our ajax callback:

$(function () {
    $('button').click(function (e) {
        e.preventDefault();
        $.get('@Url.Action("AddSpouse")', function (resp) { 
            var $form = $('form');
            $form.append(resp);                    
            $form.removeData("validator").removeData("unobtrusiveValidation");
            $.validator.u‌​nobtrusive.parse($form);
        })
    })
});
like image 62
David Wick Avatar answered Oct 02 '22 20:10

David Wick


If you want the data validation tags to be there, you need to be in a FormContext. Hence, if you're dynamically generating parts of your form, you need to include the following line in your partial view:

@{ if(ViewContext.FormContext == null) {ViewContext.FormContext = new FormContext(); }}

You then need to make sure you dynamically rebind your unobtrusive validation each time you add/remove items:

$("#form").removeData("validator");
$("#form").removeData("unobtrusiveValidation");
$.validator.unobtrusive.parse("#form");
like image 38
dazbradbury Avatar answered Oct 02 '22 19:10

dazbradbury