Unobtrusive validation doesn't work with Ajax.BeginForm
Asked Answered
M

5

34

I have View with Model1 where I put Ajax.BeginForm() and in this View i have PartialView with Model2 where i put Ajax.BeginForm(). So only in first form working unobtrusive validation. Why only in first form working validation?

first View

@model Model1

@using (Ajax.BeginForm("Action1","Controller",null,new AjaxOption(){ onSuccess = "alert('=)')"},null)
{

   <intput type="submit" value="Save" />
}


Model2 model2 = new Model2();
@Html.EditorFor(m=>model2)

**In Model2 view i have. **

@model Model2 
@using (Ajax.BeginForm("AddStreet","Controller",new AjaxOption(){onSuccess = "alert('=)'")},option,null)
{

        @Html.LabelFor(m => Model.Name):
        @Html.TextBoxFor(m => Model.Name)
        @Html.ValidationMessageFor(m => Model.Name)

       <intput type="submit" value="Save" />
}

Thanks @Darin Dimitrov for answer.

Maxim answered 19/1, 2012 at 14:40 Comment(0)
M
57

That's because the second view is loaded with AJAX at a later stage and you need to call $.validator.unobtrusive.parse(...) immediately after its contents is injected into the DOM in order to enable unobtrusive validation. Look at the following blog post for more details.

So in your case, instead of alerting in the OnSuccess callback of the first AJAX call, subscribe to a javascript function which will invoke this method:

@using (Ajax.BeginForm(
    "Action1",
    "Controller",
    null,
    new AjaxOptions { 
        OnSuccess = "onSuccess",
        UpdateTargetId = "result"
    },
    null)
)
{
    <input type="submit" value="Save" />
}

and then in your javascript file:

var onSuccess = function(result) {
    // enable unobtrusive validation for the contents
    // that was injected into the <div id="result"></div> node
    $.validator.unobtrusive.parse($(result));
};
Mafia answered 20/1, 2012 at 7:17 Comment(8)
@Sasha, in your second form you don't seem to include any input fields to be posted other than the submit button. So you are not sending anything to the server when the form is submitted.Mafia
in action i take model2.Name ... and X-Requested-WithMaxim
Try replacing @Html.TextBoxFor(m => Model.Name) with @Html.TextBoxFor(m => m.Name). Same for the label and the validation.Mafia
The Ajax.BeginForm still invoking the post method of action.Ayers
Hi all , i have done same thing as Darin answered , still not working. Any help please. One more thing in my case that i am rendering partial view in modal popup(bootstrap-modal.js)Dahle
I'm not entirely sure whey this method didn't work for me, the 'result' contained my dynamic form and no js errors were thrown by the parse method but validation did not work. I ended up passing in 'document' to the parse function and ignoring the 'result' entirely. Maybe this will help someone else?Philippians
$(result) did not work for me, instead I used $("#result"). Or one can also use new AjaxOptions { OnSuccess = "$.validator.unobtrusive.parse($('#result'));" }Kelt
@DarinDimitrov, I added your solution to my code and i works perfectly but now an annoying js error "TypeError: owner is undefined" is popping up every time. any solution?Cist
M
29

You need to add those 2 files in you Partial View even if it is already in the Shared/_Layout.cshtml:

<script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.js")" type="text/javascript"></script>

Or place this in your Partial:

<script type="text/javascript" language=javascript>
    $.validator.unobtrusive.parse(document);
</script>
Milt answered 14/1, 2013 at 1:43 Comment(4)
why need to put both on Layout and the PartialView?Egerton
its because the validation won't work, shorthand method : call it again.. Effective but not idealIrra
@Milt , I added your solution to my code and i works perfectly but now an annoying js error "TypeError: owner is undefined" is popping up every time. any solution?Cist
I've done this before, but I believe when I added jquery.validate.unobtrusive.js to both _Layout and the partial view, the form was getting submitted twice.Dissatisfaction
C
3

This solution worked best for me.

$.validator.unobtrusive.parse(document);
Cosmic answered 8/8, 2014 at 21:10 Comment(0)
V
3

The answer of Darin Dimitrov only works when validate() of the jquery validate plugin has not been called until the Ajax success handler is called. I can't think of a scenario where this could be the case, thus i wonder why the answer was accepted as correct.

Perhaps a change in the jquery validate code in the past now causes the following issue:

The issue is that validate() executes the following line first

// Check if a validator for this form was already created
var validator = $.data( this[ 0 ], "validator" );
if ( validator ) {
  return validator;

which means that the validator object is returned when validate() is called without and further handling of the options passed.

This also means that a later call to $.validator.unobtrusive.parse(...) or $.validator.unobtrusive.parseElement(...) which executes a

$form.validate(this.options) <- this.options holds the new rules parsed from HTML

to update the options of the validator has no effect because the options are not processed at all.

The solution here is to update the validator manually like

var $htmlCode = $("your html");

$.validator.unobtrusive.parse($htmlCode, true); // true means no validate() call

// now get the validation info collected in parse()
var validationInfo = $form.data("unobtrusiveValidation"); 

var $validator = $form.validate(); // get validator and ...
$validator.settings.rules = validationInfo.options.rules; // ... update its rules
$validator.settings.messages = validationInfo.options.messages; // ... update its messages

Revalidating the form (e.g. clicking submit) should now result in the expected results.

Here is a full example witch also includes code from the already accepted answer:

Razor

@using (Ajax.BeginForm(
    "Action1",
    "Controller",
    null,
    new AjaxOptions { 
        OnSuccess = "onSuccess",
        UpdateTargetId = "result"
    },
    null)
)
{
    <input type="submit" value="Save" />
}

Javascript

var onSuccess = function(result) {
    var $htmlCode = $(result);

    $.validator.unobtrusive.parse($htmlCode, true); // true means no validate() call

    // now get the validation info collected in parse()
    var validationInfo = $form.data("unobtrusiveValidation"); 

    var $validator = $form.validate(); // get validator and ...
    $validator.settings.rules = validationInfo.options.rules; // ... update its rules
    $validator.settings.messages = validationInfo.options.messages; // ... update its messages
};

--

As a side note, manually updating the validator is also possible by using the rules() method like

$yourHtmlField.rules( "add", {
  required: true,
  messages: {
    required: "Required input"
  }
});

as this directly updates the rules of the validator without the unobtrusive stuff. But then the data-val attributes are rendered useless.

Vaivode answered 29/8, 2016 at 16:17 Comment(2)
Can you give a full example for this so we don't have to splice together different bits of your solution?Aldarcy
@Aldarcy Done, i was basically only referring to the answer of Darin Dimitrov.Vaivode
P
2

You have to add a reference to jquery.unobtrusive-ajax.js to enable the validation within Ajax Form

Something like this:

<script type="text/javascript" src="/Scripts/jquery.unobtrusive-ajax.js"></script>
Pistoleer answered 19/1, 2012 at 14:43 Comment(2)
@Sasha, in View2 you didn't end the string "alert('=)') => "alert('=)')"Pistoleer
it's not it... I can't show full code.. Because it large. I think that i must use i frame and show View2 in frame.Maxim

© 2022 - 2024 — McMap. All rights reserved.