locked
How do you get validation errors to clear automatically .NET MVC5 RRS feed

  • Question

  • User-1406639494 posted

    I am having an issue with my validation with my .Net MVC5 form. When I submit my form I get the validation summary as well as the validation messages under each field that's invalid. The problem is when I start entering information into the fields, the errors don't go away like they're supposed to. I included jquery validation min underneath my form as well as jquery validation unobtrusive min but it still doesn't work for me. I can't figure out why the errors don't go away when I fix the validation errors. Also, each time my form loads it displays Please fix errors before submitting the form: in red. The errors only go away when I click submit. Maybe this has something to do with my javascript on the view page?

    This is my view page:

    <h2>Add</h2>
    
    
    <link href="~/Content/css/result-light.css" rel="stylesheet" />
    
    <link rel="stylesheet" type="text/css" href="//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css">
    
    <link href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.6-rc.0/css/select2.min.css" rel="stylesheet" />
    
    <style id="compiled-css" type="text/css">
    
        body {
            font-family: Nunito,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji" !important;
            font-size: 1rem !important;
            line-height: 1.5 !important;
        }
    
        html {
            font-size: 100% !important;
        }
    
        .col-xs-3 {
            width: 25% !important;
        }
    
        .stepwizard-step p {
            margin-top: 0px;
            color: #666;
        }
    
        .stepwizard-row {
            display: table-row;
        }
    
        .stepwizard {
            display: table;
            width: 100%;
            ;
        }
    
        .stepwizard-step button[disabled] {
            /*opacity: 1 !important;
            filter: alpha(opacity=100) !important;*/
        }
    
        .stepwizard .btn.disabled, .stepwizard .btn[disabled], .stepwizard fieldset[disabled] .btn {
            opacity: 1 !important;
            color: #bbb;
        }
    
        .stepwizard-row:before {
            top: 14px;
            bottom: 0;
            ;
            content: " ";
            width: 100%;
            height: 1px;
            background-color: #ccc;
            z-index: 0;
        }
    
        .stepwizard-step {
            display: table-cell;
            text-align: center;
            ;
        }
    
        .btn-circle {
            width: 30px;
            height: 30px;
            text-align: center;
            padding: 6px 0;
            font-size: 12px;
            line-height: 1.428571429;
            border-radius: 15px;
        }
    
        .StripeElement {
            box-sizing: border-box;
            height: 40px;
            padding: 10px 12px;
            border: 1px solid transparent;
            border-radius: 4px;
            background-color: white;
            box-shadow: 0 1px 3px 0 #e6ebf1;
            -webkit-transition: box-shadow 150ms ease;
            transition: box-shadow 150ms ease;
        }
    
        .StripeElement--focus {
            box-shadow: 0 1px 3px 0 #cfd7df;
        }
    
        .StripeElement--invalid {
            border-color: #fa755a;
        }
    
        .StripeElement--webkit-autofill {
            background-color: #fefde5 !important;
        }
    
        .green {
            border: solid green 1px;
        }
    
        .error {
            border: solid red 1px;
        }
    
        .select2-container--default .select2-selection--single {
            border: 1px solid #ccc !important;
            border-radius: 4px !important;
        }
    
            .select2-container--default .select2-selection--single .select2-selection__rendered {
                line-height: 1.428571429 !important;
                padding: 6px 12px !important;
            }
    
        .select2-container .select2-selection--single {
            height: 34px;
        }
    
        .select2-container--default .select2-selection--single .select2-selection__arrow b {
            margin-top: 0;
        }
    
        /* EOS */
    </style>
    
    <script id="insert"></script>
    
    
    
    
    <div class="container">
        <div class="stepwizard">
            <div class="stepwizard-row setup-panel">
                <div class="stepwizard-step col-xs-3">
                    <a href="#step-1" type="button" class="btn btn-success btn-circle">1</a>
                    <p><small>Personal Information</small></p>
                </div>
                <div class="stepwizard-step col-xs-3">
                    <a href="#step-2" type="button" class="btn btn-default btn-circle" disabled="disabled">2</a>
                    <p><small>Security</small></p>
                </div>
                <div class="stepwizard-step col-xs-3">
                    <a href="#step-3" type="button" class="btn btn-default btn-circle" disabled="disabled">3</a>
                    <p><small>Church Affiliation</small></p>
                </div>
                <div class="stepwizard-step col-xs-3">
                    <a href="#step-4" type="button" class="btn btn-default btn-circle" disabled="disabled">4</a>
                    <p><small>Payment</small></p>
                </div>
            </div>
        </div>
    
        @using (Html.BeginForm("Create", "Login", new { @id = string.Empty }, FormMethod.Post, new { @id = "payment-form" }))
        {
            @Html.AntiForgeryToken()
    
    
    
            <div class="panel panel-primary setup-content" id="step-1">
                <div class="panel-heading">
                    <h3 class="panel-title">Personal Information</h3>
                </div>
                <div class="panel-body">
                    @Html.ValidationSummary(false, "Please fix errors before submitting the form:", new { @class = "text-danger" })
                    <div class="row">
                        <div class="form-group col-md-6">
                            <label class="control-label">First Name</label>
                            @Html.EditorFor(model => model.FirstName, new { htmlAttributes = new { @id = "firstName", @class = "form-control", @placeholder = "Enter First Name" } })
                            @Html.ValidationMessageFor(model => model.FirstName, "", new { @class = "text-danger" })
                        </div>
    
                        <div class="form-group col-md-6">
                            <label class="control-label">Last Name</label>
                            @Html.EditorFor(model => model.LastName, new { htmlAttributes = new { @id = "lastName", @class = "form-control", @placeholder = "Enter Last Name" } })
                            @Html.ValidationMessageFor(model => model.LastName, "", new { @class = "text-danger" })
                        </div>
                    </div>
                    <div class="row">
                        <div class="form-group col-md-12">
                            <label class="control-label">Company</label>
                            @Html.EditorFor(model => model.logins.Company, new { htmlAttributes = new { @id = "company", @class = "form-control", @placeholder = "Company" } })
                            @Html.ValidationMessageFor(model => model.logins.Company, "", new { @class = "text-danger" })
                        </div>
                    </div>
                    <div class="row">
                        <div class="form-group col-md-12">
                            <label class="control-label">E-mail</label>
                            @Html.EditorFor(model => model.logins.UserName, new { htmlAttributes = new { @id = "email", @class = "form-control", @placeholder = "E-mail" } })
                            @Html.ValidationMessageFor(model => model.logins.UserName, "", new { @class = "text-danger" })
                        </div>
                    </div>
                    <div class="row">
                        <div class="form-group col-md-12">
                            <label class="control-label">Address</label>
                            @Html.EditorFor(model => model.Address, new { htmlAttributes = new { @id = "address", @class = "form-control", @placeholder = "Address" } })
                            @Html.ValidationMessageFor(model => model.logins.Address, "", new { @class = "text-danger" })
                        </div>
                    </div>
                    <div class="row">
                        <div class="form-group col-md-12">
                            <label class="control-label">Address 2</label>
                            @Html.EditorFor(model => model.Address2, new { htmlAttributes = new { @id = "address2", @class = "form-control", @placeholder = "Address2" } })
                            @Html.ValidationMessageFor(model => model.Address2, "", new { @class = "text-danger" })
                        </div>
                    </div>
                    <div class="row">
                        <div class="form-group col-md-4">
                            <label class="control-label">City</label>
                            @Html.EditorFor(model => model.logins.City, new { htmlAttributes = new { @id = "city", @class = "form-control", @placeholder = "City" } })
                            @Html.ValidationMessageFor(model => model.logins.City, "", new { @class = "text-danger" })
                        </div>
                        
                        </div>
                        <div class="form-group col-md-4">
                            <label class="control-label">Zip</label>
                            @Html.EditorFor(model => model.logins.Zip, new { htmlAttributes = new { @id = "zip", @class = "form-control", @placeholder = "Zip" } })
                            @Html.ValidationMessageFor(model => model.logins.Zip, "", new { @class = "text-danger" })
                        </div>
                    </div>
                    <div class="row">
                        <div class="form-group col-md-12">
                            <label class="control-label">Phone</label>
                            @Html.EditorFor(model => model.logins.Phone, new { htmlAttributes = new { @id = "phone", @type = "tel", @class = "form-control", @placeholder = "Phone" } })
                            @Html.ValidationMessageFor(model => model.logins.Phone, "", new { @class = "text-danger" })
                        </div>
                    </div>
                    <div class="row">
                        <div class="form-group col-md-12">
                            <label class="control-label">Cell Phone</label>
                            @Html.EditorFor(model => model.logins.CellPhone, new { htmlAttributes = new { @id = "cell", @type = "tel", @class = "form-control", @placeholder = "Cell Phone" } })
                            @Html.ValidationMessageFor(model => model.logins.CellPhone, "", new { @class = "text-danger" })
                        </div>
                    </div>
    
                    <div class="row">
                        <div class="form-group col-md-12">
                            <label class="control-label">Musician Type 1</label>
    
                            @Html.DropDownListFor(model => model.musicianTypes, new SelectList(Model.musicianTypes, "id", "TypeName"), "None", new { @id = "musicianType1", @class = "form-control" })
                            <small class="form-text"></small>
                        </div>
                    </div>
    
                    <div class="row">
                        <div class="form-group col-md-12">
                            <label class="control-label">Musician Type 2</label>
                            @Html.DropDownListFor(model => model.musicianTypes, new SelectList(Model.musicianTypes, "id", "TypeName"), "None", new { @id = "musicianType2", @class = "form-control" })
                            <small class="form-text"></small>
                        </div>
                    </div>
    
                    <button class="btn btn-primary nextBtn pull-right" type="button">Next</button>
    
    
                </div>
            </div>
            <div class="panel panel-primary setup-content" id="step-2">
                <div class="panel-heading">
                    <h3 class="panel-title">Account Security</h3>
                </div>
                <div class="panel-body">
                    <div class="row">
                        <div class="form-group col-md-12">
                            <label class="control-label">Password</label>
                            @Html.EditorFor(model => model.logins.Password, new { htmlAttributes = new { @id = "password", @type = "password", @class = "form-control", @placeholder = "Password" } })
                            @Html.ValidationMessageFor(model => model.logins.Password, "", new { @class = "text-danger" })
                            <ul class="form-text text-muted">
                                <li>Must be 8-20 characters long</li>
                                <li>Must contain at least 1 number</li>
                                <li>Must contain at least 1 uppercase letter</li>
                                <li>Must contain at least 1 lowercase letter </li>
                                <li>Must contain a special character (e.g. ! ; # * %)</li>
                            </ul>
                        </div>
                    </div>
                    <div class="row">
                        <div class="form-group col-md-12">
                            <label class="control-label">Confirm Password</label>
                            @Html.EditorFor(model => model.ConfirmPassword, new { htmlAttributes = new { @id = "cnfPassword", @type = "password", @class = "form-control", @placeholder = "Confirm Password" } })
                            @Html.ValidationMessageFor(model => model.ConfirmPassword, "", new { @class = "text-danger" })
                        </div>
                    </div>
    
                    <div class="row">
                        <div class="form-group col-md-12">
                            <label class="control-label">Security Question</label>
                            @Html.DropDownListFor(model => model.chlist, new SelectList(Model.seclist, "id", "Question"), "Select", new { @id = "securityQuestion", @class = "form-control" })
                            <small class="form-text"></small>
                        </div>
                    </div>
    
                    <div class="row">
                        <div class="form-group col-md-12">
                            <label class="control-label">Security Answer</label>
                            @Html.EditorFor(model => model.logins.SecretAnswer, new { htmlAttributes = new { @id = "answer", @type = "text", @class = "form-control", @placeholder = "Security Question Answer" } })
                            @Html.ValidationMessageFor(model => model.logins.SecretAnswer, "", new { @class = "text-danger" })
                        </div>
                    </div>
    
                    <div class="row">
                        <div class="form-group col-md-12">
                            <label class="control-label">Account PIN</label>
                            @Html.EditorFor(model => model.logins.AccountPasscode, new { htmlAttributes = new { @id = "pin", @maxlength = "6", @type = "password", @class = "form-control", @placeholder = "Pin" } })
                            @Html.ValidationMessageFor(model => model.logins.AccountPasscode, "", new { @class = "text-danger" })
                            <small class="form-text"></small>
                        </div>
                    </div>
                    <button class="btn btn-primary nextBtn pull-right" type="button">Next</button>
    
                </div>
            </div>
            <div class="panel panel-primary setup-content" id="step-3">
                <div class="panel-heading">
                    <h3 class="panel-title">Church Affiliation</h3>
                </div>
                <div class="panel-body">
    
                    <div class="row">
                        <div class="form-group col-md-12">
                            <label class="control-label">Church Affiliation 1</label><br />
                            @Html.DropDownListFor(model => model.chlist, new SelectList(Model.chlist, "id", "ChurchName"), "None", new { @id = "churchAffiliation1", @class = "select2 form-control", @style = "width:100%" })
    
                            <small class="form-text"></small>
                        </div>
                    </div>
                    <div class="row">
                        <div class="form-group col-md-12">
                            <label class="control-label">Church Affiliation 2</label><br />
                            @Html.DropDownListFor(model => model.chlist, new SelectList(Model.chlist, "id", "ChurchName"), "None", new { @id = "churchAffiliation2", @class = "select2 form-control", @style = "width:100%" })
                            <small class="form-text"></small>
                        </div>
                    </div>
                    <div class="row">
                        <div class="form-group col-md-12">
                            <label class="control-label">Church Affiliation 1</label><br />
                            @Html.DropDownListFor(model => model.chlist, new SelectList(Model.chlist, "id", "ChurchName"), "None", new { @id = "churchAffiliation3", @class = "select2 form-control", @style = "width:100%" })
    
                            <small class="form-text"></small>
                        </div>
                    </div>
                    <div class="row">
                        <div class="form-group col-md-12">
                            <label class="control-label">Church Affiliation 4</label><br />
                            @Html.DropDownListFor(model => model.chlist, new SelectList(Model.chlist, "id", "ChurchName"), "None", new { @id = "churchAffiliation4", @class = "select2 form-control", @style = "width:100%" })
                            <small class="form-text"></small>
                        </div>
                    </div>
                    <button class="btn btn-primary nextBtn pull-right" type="button">Next</button>
                </div>
    
            </div>
    
            <div class="panel panel-primary setup-content" id="step-4">
                <div class="panel-heading">
                    <h3 class="panel-title">Payment</h3>
                </div>
                <div class="panel-body">
    
                    <div class="form-group">
                        <label for="cardName">Name on Card</label>
                        @Html.EditorFor(model => model.logins.Name, new { htmlAttributes = new { @id = "cardName", @class = "form-control", @placeholder = "Name On Card" } })
                        @Html.ValidationMessageFor(model => model.logins.Name, "", new { @class = "text-danger" })
                    </div>
    
                    <row>
                        <div class="form-group">
                            <label for="plan" class="control-label">Select a Plan</label><br />
                            @Html.DropDownListFor(model => model.subscriptionTypes, new SelectList(Model.subscriptionTypes, "id", "SubscriptionType1"), "None", new { @id = "plan", @class = "form-control" })
    
                        </div>
    
                        <div class="form-group">
                            <label for="card-number">
                                Credit or debit card
                            </label>
                            <div id="card-number">
                                <!-- A Stripe Element will be inserted here. -->
                            </div>
                        </div>
    
                        <div class="form-group">
                            <div class="row">
                                <div class="col-md-6">
                                    <label for="card-vc">
                                        CVC
                                    </label>
                                    <div id="card-cvc">
                                        <!-- A Stripe Element will be inserted here. -->
                                    </div>
                                </div>
                                <div class="col-md-6">
                                    <label for="card-expiration">
                                        Exp
                                    </label>
                                    <div id="card-expiration">
                                        <!-- A Stripe Element will be inserted here. -->
                                    </div>
                                </div>
                            </div>
                        </div>
                        <!-- Used to display form errors. -->
                        <div id="card-errors" role="alert"></div>
    
    
                        <div class="form-group">
                            <button class="form-control btn btn-primary" type="submit">Submit Payment</button>
                        </div>
                </div>
            </div>
        }
    </div>
    
    
    <script type="text/javascript">
    
    
    
        $(document).ready(function () {
    
            var navListItems = $('div.setup-panel div a'),
                allWells = $('.setup-content'),
                allNextBtn = $('.nextBtn');
    
            allWells.hide();
    
            navListItems.click(function (e) {
                e.preventDefault();
                var $target = $($(this).attr('href')),
                    $item = $(this);
    
                if (!$item.hasClass('disabled')) {
                    navListItems.removeClass('btn-success').addClass('btn-default');
                    $item.addClass('btn-success');
                    allWells.hide();
                    $target.show();
                    $target.find('input:eq(0)').focus();
                }
            });
    
            allNextBtn.click(function () {
                var curStep = $(this).closest(".setup-content"),
                    curStepBtn = curStep.attr("id"),
                    nextStepWizard = $('div.setup-panel div a[href="#' + curStepBtn + '"]').parent().next().children("a"),
                    curInputs = curStep.find("input, select"),
                    isValid = true;
    
                $(".form-group").removeClass("has-error");
                for (var i = 0; i < curInputs.length; i++) {
                    if (!curInputs[i].validity.valid) {
                        isValid = false;
                        $(curInputs[i]).closest(".form-group").addClass("has-error");
                    }
                }
    
                if (isValid) nextStepWizard.removeAttr('disabled').trigger('click');
            });
    
            $('div.setup-panel div a.btn-success').trigger('click');
        });
    
    
    </script>
    
    <script>
        $('.select2').select2();
    </script>

    This is what in imported in my _Layout :

    <!-- Custom fonts for this template-->
        <link href="~/Content/AdminTemplate/vendor/fontawesome-free/css/all.min.css" rel="stylesheet" type="text/css">
        <link href="https://fonts.googleapis.com/css?family=Nunito:200,200i,300,300i,400,400i,600,600i,700,700i,800,800i,900,900i" rel="stylesheet">
        <link rel="stylesheet" href="~/Content/bootstrap-datetimepicker.css" />
    
        <!-- Custom styles for this template-->
        <link href="~/Content/AdminTemplate/css/sb-admin-2.min.css" rel="stylesheet">
        <link href="~/Content/AdminTemplate/vendor/datatables/dataTables.bootstrap4.min.css" rel="stylesheet">
    
        <script src="~/Scripts/jquery-3.4.1.js"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.6-rc.0/js/select2.min.js"></script>
    
    <!-- Bootstrap core JavaScript-->
        
        <script src="~/Scripts/jquery.validate.min.js"></script>
        <script src="~/Scripts/jquery.validate.unobtrusive.min.js"></script>
        <script src="~/Content/AdminTemplate/vendor/bootstrap/js/bootstrap.bundle.min.js"></script>
    
        <!-- Core plugin JavaScript-->
        <script src="~/Content/AdminTemplate/vendor/jquery-easing/jquery.easing.min.js"></script>
    
        <!-- Custom scripts for all pages-->
        <script src="~/Content/AdminTemplate/js/sb-admin-2.min.js"></script>
    
        <!-- Page level plugins -->
        <script src="~/Content/AdminTemplate/vendor/chart.js/Chart.min.js"></script>
    
        <!-- Page level custom scripts -->
        <script src="~/Content/AdminTemplate/js/demo/chart-area-demo.js"></script>
        <script src="~/Content/AdminTemplate/js/demo/chart-pie-demo.js"></script>
    
        <!-- Page level plugins -->
        <script src="~/Content/AdminTemplate/vendor/datatables/jquery.dataTables.min.js"></script>
        <script src="~/Content/AdminTemplate/vendor/datatables/dataTables.bootstrap4.min.js"></script>
    
        <!-- Page level custom scripts -->
        <script src="~/Content/AdminTemplate/js/demo/datatables-demo.js"></script>
    
        @RenderSection("stripe", required: false)
    </body>
    </html>
    This is my controller:


    public ActionResult Create() { if (string.IsNullOrEmpty(Convert.ToString(Session["UserName"]))) { return RedirectToAction("Login", "Home"); } /* var mymodel = new LoginSecurityQuestionsViewModel(); mymodel.logins = db.logins.ToList(); ViewBag.securityquestions = db.secretquestions.ToList(); ViewBag.churches = db.churches.ToList(); ViewBag.subscriptionTypes = db.subscriptiontypes.ToList(); ViewBag.musicianTypes = db.musiciantypes.ToList(); return View(mymodel);*/ LoginSecurityQuestionsViewModel multi_Dropdownlist = new LoginSecurityQuestionsViewModel { seclist = GetSecurityQuestionList(), chlist = GetChurchList(), subscriptionTypes = GetSubscriptionTypes(), musicianTypes = GetMusicianTypes() }; return View(multi_Dropdownlist); } // POST: login/Create // To protect from overposting attacks, enable the specific properties you want to bind to, for // more details see https://go.microsoft.com/fwlink/?LinkId=317598. [HttpPost] public ActionResult Create(ChargeDTO chargeDto) { if (ModelState.IsValid == false) { LoginSecurityQuestionsViewModel multi_Dropdownlist = new LoginSecurityQuestionsViewModel { seclist = GetSecurityQuestionList(), chlist = GetChurchList(), subscriptionTypes = GetSubscriptionTypes(), musicianTypes = GetMusicianTypes() }; return View(multi_Dropdownlist); } }

    Wednesday, September 9, 2020 9:40 PM

All replies

  • User-474980206 posted

    that is the way the summary works. it is only cleared on submit. on submit, its cleared, and new errors are displayed if any. if you want the error to clear as each message is cleared you will need to write your own summary.

    if you review the jquery validation, and unobtrusive code, you will see the validation summary is tied to the invalidHandler (which is called after submit or .valid()), and the validation messages are tied to errorPlacement and success options (called after a field validation triggered by noblur or submit, or valid()). 

    one issue with the current validation summary is it just renders <ul>{message}</ul> and does not include the field mapping. you will need to change this rendering to have the filename, so the success callback can clear it. say

      <ul data-val-name="{fieldname}">{message}</ul>

    Wednesday, September 9, 2020 10:15 PM
  • User-1406639494 posted

    Thanks for your quick reply. I see what you are saying but why does it work correctly on the default pages? If I use another page it works fine. It's just this page that is the problem. I want the errors to go away under each text box as I correct them.

    Thursday, September 10, 2020 4:04 PM
  • User-474980206 posted

    if you are talking the validation message for a field and not the summary, then you new page has probably not triggered a submit. the default behavior of jquery validation is to not validate any fields until submit (lazy mode). once a submit has happened, then a validation of each field is done on blur.

    I haven't used jquery validation for years (switched to react.js), but a quick view of the code shows that the field in error must be in the submitted map, which is filled in on a submit.

    while this is the focus out, the same test of "element.name in this.submitted" is performed on the other one field validation event (keyup, click, etc). the form() method is what is called to validate a form, and it sets submitted by coping the error map.

    onfocusout: function( element ) {
    			if ( !this.checkable( element ) && ( element.name in this.submitted || !this.optional( element ) ) ) {
    				this.element( element );
    			}
    		},
    		form: function() {
    			this.checkForm();
    			$.extend( this.submitted, this.errorMap );
    			this.invalid = $.extend( {}, this.errorMap );
    			if ( !this.valid() ) {
    				$( this.currentForm ).triggerHandler( "invalid-form", [ this ] );
    			}
    			this.showErrors();
    			return this.valid();
    		},

    Thursday, September 10, 2020 5:55 PM