0

I am facing a very strange problem. I have created new asp.net mvc5 application. and I upgrade it to asp.net mvc-5.2.2. Now I have the following field:-

 [Required]
 [StringLength(200)]
 public string Name { get; set; }

And when I render a partial view as a modal popup, and i leave a required field emtoy, I will get the validation error when trying to submit the form (which is correct) :-

enter image description here

But the strange problem is that , when I added the following data annotation to my model class:-

 [Required]
        [StringLength(200)]
      [DataType(DataType.MultilineText)]
        public string Name { get; set; }

Then the whole client side validation will break inside the modal partial view. And I will be able to submit the partial view even when leaving the Name field empty (as no client validation error will be displayed), but if I remove the [DataType(DataType.MultilineText)] I will get the validation working again.. This is very strange problem and I can not understand what is going on …

Here is the script which is responsible for displaying the partial view as modal popup & for validating the partial view:-

 $(function () {
        $.ajaxSetup({ cache: false });
        $("a[data-modal]").on("click", function (e) {        
            $('#myModalContent').load(this.href, function () {
                $('#myModal').modal({
                    keyboard: true
                }, 'show');

                bindForm(this);
            });
            return false;
        });


    });

    function bindForm(dialog) {
        $('form', dialog).submit(function () {
               var isValid = true; // assume all OK
            $('form').validate(); // perform validation on the form
              $('input[type="text"]').each(function (index, item) { // could change selector to suit e.g $('input, textarea').each(..            
            if (!$(this).valid()) {
                  isValid = false; // signal errors
                     return false; // break out of loop   
                 }
             })
              if (!isValid) {
                  return false; // exit
              }
            $('#progress').show();
            $.ajax({
                url: this.action,
                type: this.method,
                data: $(this).serialize(),
                success: function (result) {
                    if (result.success) {
                        $('#myModal').modal('hide');
                        $('#progress').hide();
                        location.reload();
                    } else {
                        $('#progress').hide();
                        $('#myModalContent').html(result);
                        bindForm();
                    }
                }
            });
            return false;
        });
    }

i tried re-producing this problem on an asp.net mvc 5.0 but seems everything is working well, could this be a problem inside mvc 5.2.2 only?

EDIT

here is the markup for the name field inside the popup modal (the client side validation is not working on it):-

<div class="form-group">
            <label class="control-label col-md-2" for="Name">Name</label>
            <div class="col-md-10">
                <textarea class="input-validation-error text-box multi-line" data-val="true" data-val-length="The field Name must be a string with a maximum length of 200." data-val-length-max="200" data-val-required="The Name field is required." id="Name" name="Name"></textarea> 
                <span class="field-validation-error" data-valmsg-for="Name" data-valmsg-replace="true">The Name field is required.</span>
            </div>
        </div>

while here is when i rendered it inside the browser as full view (client side validation will work) :-

<div class="form-group">
            <label class="control-label col-md-2" for="Name">Name</label>
            <div class="col-md-10">
                <textarea class="text-box multi-line" data-val="true" data-val-length="The field Name must be a string with a maximum length of 200." data-val-length-max="200" data-val-required="The Name field is required." id="Name" name="Name"></textarea> 
                <span class="field-validation-valid" data-valmsg-for="Name" data-valmsg-replace="true"></span>
            </div>
        </div>

and when i remove the [DataType.MultiLineText] data annotation the markup will be :-

<div class="form-group">
            <label class="control-label col-md-2" for="Name">Name</label>
            <div class="col-md-10">
                <input class="text-box single-line" data-val="true" data-val-length="The field Name must be a string with a maximum length of 200." data-val-length-max="200" data-val-required="The Name field is required." id="Name" name="Name" type="text" value=""> 
                <span class="field-validation-valid" data-valmsg-for="Name" data-valmsg-replace="true"></span>
            </div>
        </div>

EDIT2 now my script (skillmanagementgrid) looks as follow:-

$(function () {
    $.ajaxSetup({ cache: false });
    $("a[data-modal]").on("click", function (e) {
        $('#myModalContent').load(this.href, function () {
            $('#myModal').modal({
                keyboard: false
            }, 'show');
            $("form").removeData("validator");
            $("form").removeData("unobtrusiveValidation");
            $.validator.unobtrusive.parse("form");
            bindForm(this);
        });
        return false;
    });


});

function bindForm(dialog) {
    $('form', dialog).submit(function () {
          var isValid = true; // assume all OK
          if ($('form').valid()) { // perform validation on the form

              //  $('input[type="text"],input[type="textarea"]').each(function (index, item) { // could change selector to suit e.g $('input, textarea').each(..            
              //       if (!$(this).valid()) {
              //          isValid = false; // signal errors
              //           return false; // break out of loop   
              //  }
              //})
              //       if (!isValid) {
              //         return false; // exit
              //    }
              $('#progress').show();
              $.ajax({
                  url: this.action,
                  type: this.method,
                  data: $(this).serialize(),
                  success: function (result) {
                      if (result.success) {
                          $('#myModal').modal('hide');
                          $('#progress').hide();
                          location.reload();

                      } else {

                          $('#progress').hide();
                          $('#myModalContent').html(result);
                          bindForm();
                      }
                  }
              });
          }
        return false;
    });
}

and my Index view script section is :-

@section scripts{


    @Scripts.Render("~/bundles/jqueryval") 
  <script src="~/Scripts/skillmanagementgrid.js"></script>
}

currently if i submit the modal popup while leaving a required field empty, the script "if ($('form').valid())" will return true ? and also the return false will be called .but at the end the modal popp will be submitted even if it have validation errors. i am 100% confused ? can you please adivce ?

EDIT 3 now i have updated my code as follow:-

$(function () {
    $.ajaxSetup({ cache: false });
    $("a[data-modal]").on("click", function (e) {

        $('#myModalContent').load(this.href, function () {
            $('#myModal').modal({
                keyboard: true
            }, 'show');
            $('#myModalContent').removeData("validator");
            $('#myModalContent').removeData("unobtrusiveValidation");
            $.validator.unobtrusive.parse('#myModalContent');
            bindForm(this);
        });
        return false;
    });


});

function bindForm(dialog) {
    $('#myModalContent', dialog).submit(function () {

        if ($('#myModalContent').valid()) {
            $('#progress').show();
            $.ajax({
                url: this.action,
                type: this.method,
                data: $(this).serialize(),
                success: function (result) {
                    if (result.success) {
                        $('#myModal').modal('hide');
                        $('#progress').hide();
                        //location.reload();
                        alert('www');
                    } else {

                        $('#progress').hide();
                        $('#myModalContent').html(result);
                        bindForm();
                    }
                }
            });
     }
        else {
           return false;
   }
    });
}

now the form validation is working , but when i submit the modal popup form , it will send a normal http post request and not an Ajax post request... so not sure how to get this working,,, i need to have both form validation working & also to have the Script sending ajax post request... can u adivce what is wrong inside my code? Thanks

John John
  • 1
  • 72
  • 238
  • 501
  • 1
    can you show what `html` will be rendered with and without attribute? Also, don't you want just use `@Html.TextAreaFor()` helper to achive same result? – teo van kot Jan 16 '15 at 18:39
  • can you check my edit to the original question , i have provided the markup . – John John Jan 16 '15 at 22:29

1 Answers1

1

Well as i can see from html markup validation should work in modal popup.

I think you have problem because when you render popup menu you basicaly change DOM with your ajax response and unobtrusive validation should parse html that was added, i just can't see it in your js. You can do it like this i think:

$(function () {
    $.ajaxSetup({ cache: false });
    $("a[data-modal]").on("click", function (e) {
        $('#myModalContent').load(this.href, function () {
            $('#myModal').modal({
                keyboard: true
            }, 'show');
            // this is how you parse added DOM with form to perform validation
            // here could be just 'form' selector if you sure that you have only one form
            $.validator.unobtrusive.parse($("#myModalContent"));
            bindForm(this);
        });
        return false;
    });
});

function bindForm(dialog) {
    $('form', dialog).submit(function () {
        if ($('form').valid()) {
            $('#progress').show();
            $.ajax({
                url: this.action,
                type: this.method,
                data: $(this).serialize(),
                success: function (result) {
                    if (result.success) {
                        $('#myModal').modal('hide');
                        $('#progress').hide();
                        location.reload();
                    } else {
                        $('#progress').hide();
                        $('#myModalContent').html(result);
                        bindForm();
                    }
                }
            });
        }
        else
        {
            return false;
        }
    });
}

Now about [DataType.MultiLineText] attribute. I can't see any problems in html, so i suppose it should work too. But i prefer to use @Html.TextAreaFor() helper on View to render textarea instead of Attribute becouse if you decide to change it you don't heed to reduild your project. You can do it like this on your View i suppose:

@Html.TextAreaFor(x => x.Name)
teo van kot
  • 12,350
  • 10
  • 38
  • 70
  • thanks again, i read that we need to remove the previous loaded validators, as i have the following @Scripts.Render("~/bundles/jqueryval") inside the Index view as shown on my Edit2 code ... not sure what you mean exactly by one form ,, i have the Index view which will have a modal popup above it (in fron of it) containing the partial view ? so does this mean i have two forms ? – John John Jan 19 '15 at 12:22
  • 1
    you don't need to remove previos validators you anly need to parse new html that comes with ajax to add validation handlers, that's what my js string suppose to do. I hope that you don't add links to scripts on your `partialView` couse it's really wrond and can work not in all cases. about `form` i mean that you use form selector in your validation so if you have more than one `form` selector on your view it can work wrong way. Just search your rendered html in brouser for `form` tags. – teo van kot Jan 19 '15 at 12:26
  • now i copy and paste your script , and i reference the following inside the Index main view "@Scripts.Render("~/bundles/jqueryval") " but still the modal popup form can be submitted even with validation error inside it .... – John John Jan 19 '15 at 15:08
  • now inside my Script i replaced all the ($('form') to be ($('#myModalContent') and now i get the validation working fine ??? can you adivce if using "($('#myModalContent')" instead of ($('form') is wrong, i did this because on the main view i have a form which contain a search button,, so inside my script when i was using $('form') the script could have been validating the seach form inside the main view instead of the partial view ?? can you advice ? – John John Jan 19 '15 at 15:10
  • 1
    At last you get my comments :) it's ok to use your unique selector to validate your form. But in my projects i trying to create unique id's for forms, just becouse it's cleanier and easy to understand in future. – teo van kot Jan 19 '15 at 18:26
  • but how i can keep using ($('form') incase i already have forms such as search form inside the main view,, as in this case the java script code will be validating the main view form instead the modal popup form ? can you adivce ? i am trying also to keep my code clean ... – John John Jan 20 '15 at 01:58
  • 1
    You can use `$('#myModalContent form')` selector. I can ref to form id becouse i generate it dynamicaly. – teo van kot Jan 20 '15 at 04:11
  • can you check my Edit3 section inside my original question? as now when i submit the modal popup view it will send a normal http post request and not ajax post request as mentioned in my script ? can you check and adivce please? – John John Jan 20 '15 at 15:40
  • It's more and more looks like remote lesson :) check what's inside this.method property, maby you should change the value with just 'post'? – teo van kot Jan 20 '15 at 20:39
  • now i define if($(this).valid()) and it worked well, seems 'form'.valid() will return a list of properties ,, while if($(this).valid()) will validate the form correctly.. – John John Jan 21 '15 at 00:39
  • 1
    wierd, in my code i use `'form'` selector and `valid()` method returns `true` or `false`. – teo van kot Jan 22 '15 at 08:44
  • i am not sure what is the problem, but ('form').valid will not work unless i have to check each item separately , while if i define the following "function bindForm(dialog) { $('form', dialog).submit(function () { if ($(this).valid()) {" so i use (this).valid() instead of ('form').valid() will work for me? so is using (this).valid() considered a wrong approach ? – John John Jan 22 '15 at 12:13
  • i can't see anything wrong with `(this)` if it helps you to solve your problem =) – teo van kot Jan 22 '15 at 12:17
  • i asked the [question](http://stackoverflow.com/q/28090143/1849444) and the answers should solve all your question about validation ViewModel in MVC. Take a look =) – teo van kot Jan 26 '15 at 11:52
  • I hope our discution helps you a lot =) – teo van kot Jan 26 '15 at 13:19