locked
Prevent Wizard Next Button From Progressing Unless Each Tab of the Wizard is Validated RRS feed

  • Question

  • User-1970057224 posted

    I have a wizard in my MVC5 project that uses the built in validation from MVC. I would like to prevent the wizard from progressing unless the current tab passes validation. As far as I know, the MVC validation only validates when the user clicks submit. How do I prevent the user from going on to the next tab in the wizard when they click the next button unless all fields are valid? I tried to do it in Javascript but it didn't work. Is there a way to do this in C# MVC? If not, can someone explain why my javascript is not working to validate?

    Controller:

    [HttpPost]
            public ActionResult Create(LoginSecurityQuestionsViewModel chargeDto)
            {
                
                if (ModelState.IsValid == false)
                {
                    LoginSecurityQuestionsViewModel viewModel = new LoginSecurityQuestionsViewModel();
                    viewModel.chlist1 = new SelectList((from s in db.churches
                                                        select new
                                                        {
                                                            ID = s.id,
                                                            FullName = s.ChurchName + " " + s.ChuchDenomination + " " + s.ChurchType + " - " + s.ChurchCity + ", " + s.ChurchState
                                                        }),
                                                        "ID",
                                                        "FullName");
                    viewModel.chlist2 = new SelectList((from s in db.churches
                                                        select new
                                                        {
                                                            ID = s.id,
                                                            FullName = s.ChurchName + " " + s.ChuchDenomination + " " + s.ChurchType + " - " + s.ChurchCity + ", " + s.ChurchState
                                                        }),
                                                        "ID",
                                                        "FullName");
                    viewModel.chlist3 = new SelectList((from s in db.churches
                                                        select new
                                                        {
                                                            ID = s.id,
                                                            FullName = s.ChurchName + " " + s.ChuchDenomination + " " + s.ChurchType + " - " + s.ChurchCity + ", " + s.ChurchState
                                                        }),
                                                        "ID",
                                                        "FullName");
                    viewModel.chlist4 = new SelectList((from s in db.churches
                                                        select new
                                                        {
                                                            ID = s.id,
                                                            FullName = s.ChurchName + " " + s.ChuchDenomination + " " + s.ChurchType + " - " + s.ChurchCity + ", " + s.ChurchState
                                                        }),
                                                        "ID",
                                                        "FullName");
                    viewModel.seclist = new SelectList(db.secretquestions, "id", "Question");
                    viewModel.subscriptionTypes = new SelectList((from s in db.subscriptiontypes
                                                                  select new
                                                                  {
                                                                      ID = s.StripePriceID,
                                                                      FullName = s.SubscriptionType1 + " - $" + s.Price + "/Month "
                                                                  }),
                                                        "ID",
                                                        "FullName");
                    viewModel.musicianTypes1 = new SelectList(db.musiciantypes, "id", "TypeName");
                    viewModel.musicianTypes2 = new SelectList(db.musiciantypes, "id", "TypeName");
    
                    return View(viewModel);
                }
    

    This is the view with the javascript:

    <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, "", 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.Company, new { htmlAttributes = new { @id = "company", @class = "form-control", @placeholder = "Company" } })
                            @Html.ValidationMessageFor(model => model.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.Email, new { htmlAttributes = new { @id = "email", @class = "form-control", @placeholder = "E-mail" } })
                            @Html.ValidationMessageFor(model => model.Email, "", 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.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.City, new { htmlAttributes = new { @id = "city", @class = "form-control", @placeholder = "City" } })
                            @Html.ValidationMessageFor(model => model.City, "", new { @class = "text-danger" })
                        </div>
                        <div class="form-group col-md-4">
                            <label class="control-label">State</label>
                            @Html.DropDownList("State", new List<SelectListItem>
    
                            {
                                new SelectListItem{ Text="Select", Value = "" },
                                new SelectListItem{ Text="Alabama", Value = "AL" },
                                new SelectListItem{ Text="Alaska", Value = "AK" },
                                new SelectListItem{ Text="American Samoa", Value = "AS" },
                                new SelectListItem{ Text="Arizona", Value = "AZ" },
                                new SelectListItem{ Text="Arkansas", Value = "AR" },
                                new SelectListItem{ Text="California", Value = "CA" },
                                new SelectListItem{ Text="Colorado", Value = "CO" },
                                new SelectListItem{ Text="Connecticut", Value = "CT" },
                                new SelectListItem{ Text="Delaware", Value = "DE" },
                                new SelectListItem{ Text="District of Columbia", Value = "DC" },
                                new SelectListItem{ Text="Florida", Value = "FL" },
                                new SelectListItem{ Text="Georgia", Value = "GA" },
                                new SelectListItem{ Text="Guam", Value = "GU" },
                                new SelectListItem{ Text="Hawaii", Value = "HI" },
                                new SelectListItem{ Text="Idaho", Value = "ID" },
                                new SelectListItem{ Text="Ilinois", Value = "IL" },
                                new SelectListItem{ Text="Indiana", Value = "IN" },
                                new SelectListItem{ Text="Iowa", Value = "IA" },
                                new SelectListItem{ Text="Kansas", Value = "KS" },
                                new SelectListItem{ Text="Kentucky", Value = "KY" },
                                new SelectListItem{ Text="Louisiana", Value = "LA" },
                                new SelectListItem{ Text="Maine", Value = "ME" },
                                new SelectListItem{ Text="Maryland", Value = "MD" },
                                new SelectListItem{ Text="Massachusetts", Value = "MA" },
                                new SelectListItem{ Text="Michigan", Value = "MI" },
                                new SelectListItem{ Text="Minnesota", Value = "MN" },
                                new SelectListItem{ Text="Mississippi", Value = "MS" },
                                new SelectListItem{ Text="Missouri", Value = "MO" },
                                new SelectListItem{ Text="Montana", Value = "MT" },
                                new SelectListItem{ Text="Nebraska", Value = "NE" },
                                new SelectListItem{ Text="Nevada", Value = "NV" },
                                new SelectListItem{ Text="New Hampshire", Value = "NH" },
                                new SelectListItem{ Text="New Jersey", Value = "NJ" },
                                new SelectListItem{ Text="New Mexico", Value = "NM" },
                                new SelectListItem{ Text="New York", Value = "NY" },
                                new SelectListItem{ Text="North Dakota", Value = "ND" },
                                new SelectListItem{ Text="Northern Mariana Island", Value = "MP" },
                                new SelectListItem{ Text="Ohio", Value = "OH" },
                                new SelectListItem{ Text="Oaklahoma", Value = "OK" },
                                new SelectListItem{ Text="Oregon", Value = "OR" },
                                new SelectListItem{ Text="Pennsylvania", Value = "PA" },
                                new SelectListItem{ Text="Puerto Rico", Value = "PR" },
                                new SelectListItem{ Text="Rhode Island", Value = "RI" },
                                new SelectListItem{ Text="South Carolina", Value = "SC" },
                                new SelectListItem{ Text="South Dakota", Value = "SD" },
                                new SelectListItem{ Text="Tennessee", Value = "TN" },
                                new SelectListItem{ Text="Texas", Value = "TX" },
                                new SelectListItem{ Text="Utah", Value = "UT" },
                                new SelectListItem{ Text="Vermont", Value = "VT" },
                                new SelectListItem{ Text="Virginia", Value = "VA" },
                                new SelectListItem{ Text="Virgin Islands", Value = "VI" },
                                new SelectListItem{ Text="Washington", Value = "WA" },
                                new SelectListItem{ Text="West Virginia", Value = "WV" },
                                new SelectListItem{ Text="Wisconsin", Value = "WI" },
                                new SelectListItem{ Text="Wyoming", Value = "WY" },
    
                            }, new { @id = "state", @class = "form-control" })
                            @Html.ValidationMessageFor(model => model.State, "", new { @class = "text-danger" })
                        </div>
                        <div class="form-group col-md-4">
                            <label class="control-label">Zip</label>
                            @Html.EditorFor(model => model.Zip, new { htmlAttributes = new { @id = "zip", @class = "form-control", @placeholder = "Zip" } })
                            @Html.ValidationMessageFor(model => model.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.Phone, new { htmlAttributes = new { @id = "phone", @type = "tel", @class = "form-control", @placeholder = "Phone" } })
                            @Html.ValidationMessageFor(model => model.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.Cell, new { htmlAttributes = new { @id = "cell", @type = "tel", @class = "form-control", @placeholder = "Cell Phone" } })
                            @Html.ValidationMessageFor(model => model.Cell, "", 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.musicianType1id, Model.musicianTypes1, "None", new { @id = "musicianType1", @class = "form-control" })
                            @Html.ValidationMessageFor(model => model.musicianType1id, "", new { @class = "text-danger" })
                        </div>
                    </div>
    
                    <div class="row">
                        <div class="form-group col-md-12">
                            <label class="control-label">Musician Type 2</label>
                            @Html.DropDownListFor(model => model.musicianType2id, Model.musicianTypes2, "None", new { @id = "musicianType2", @class = "form-control" })
                            @Html.ValidationMessageFor(model => model.musicianType2id, "", new { @class = "text-danger" })
                        </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.Password, new { htmlAttributes = new { @id = "password", @type = "password", @class = "form-control", @placeholder = "Password" } })
                            @Html.ValidationMessageFor(model => model.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.seclistid, Model.seclist, "Select", new { @id = "securityQuestion", @class = "form-control" })
                            @Html.ValidationMessageFor(model => model.seclistid, "", new { @class = "text-danger" })
                        </div>
                    </div>
    
                    <div class="row">
                        <div class="form-group col-md-12">
                            <label class="control-label">Security Answer</label>
                            @Html.EditorFor(model => model.Answer, new { htmlAttributes = new { @id = "answer", @type = "text", @class = "form-control", @placeholder = "Security Question Answer" } })
                            @Html.ValidationMessageFor(model => model.Answer, "", 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.Pin, new { htmlAttributes = new { @id = "pin", @maxlength = "6", @type = "password", @class = "form-control", @placeholder = "Pin" } })
                            @Html.ValidationMessageFor(model => model.Pin, "", new { @class = "text-danger" })
    
                        </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.chlist1id, Model.chlist1, "None", new { @id = "churchAffiliation1", @class = "select2 form-control", @style = "width:100%" })
                            @Html.ValidationMessageFor(model => model.chlist1id, "", new { @class = "text-danger" })
                        </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.chlist2id, Model.chlist2, "None", new { @id = "churchAffiliation2", @class = "select2 form-control", @style = "width:100%" })
                            @Html.ValidationMessageFor(model => model.chlist2id, "", new { @class = "text-danger" })
                        </div>
                    </div>
                    <div class="row">
                        <div class="form-group col-md-12">
                            <label class="control-label">Church Affiliation 3</label><br />
                            @Html.DropDownListFor(model => model.chlist3id, Model.chlist3, "None", new { @id = "churchAffiliation3", @class = "select2 form-control", @style = "width:100%" })
                            @Html.ValidationMessageFor(model => model.chlist3id, "", new { @class = "text-danger" })
                        </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.chlist4id, Model.chlist4, "None", new { @id = "churchAffiliation4", @class = "select2 form-control", @style = "width:100%" })
                            @Html.ValidationMessageFor(model => model.chlist4id, "", new { @class = "text-danger" })
                        </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">
                    <row>
                        <div class="form-group">
                            <label for="plan" class="control-label">Select a Plan</label><br />
                            @Html.DropDownListFor(model => model.planid, Model.subscriptionTypes, "None", new { @id = "plan", @class = "form-control" })
                            @Html.ValidationMessageFor(model => model.planid, "", new { @class = "text-danger" })
                        </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>
    Saturday, September 12, 2020 1:33 AM

All replies

  • User-474980206 posted

    One approach would be to make each wizard page its own form and use Ajax. The other is to use the jquery validation ignore option. You could make it a function that ignored all fields but ones in the current wizard page, or use a selector and on wizard navigation add the ignore class to the other pages fields.

    Saturday, September 12, 2020 2:50 PM
  • User1686398519 posted

    Hi steven85791,  

    steven85791

    Javascript but it didn't work

    1. You can check whether there is an error message in the console through F12 in the browser.
    2. If an error message similar to "Uncaught ReferenceError: $ is not defined" appears, the page must not load the jquery file.Here is the solution:
      1. If your page uses the layout view
        1. If you did not modify your layout view, then your layout view has:
          • @Scripts.Render("~/bundles/jquery")@*jquery is already quoted here.*@
            @Scripts.Render("~/bundles/bootstrap")
            @RenderSection("scripts", required: false)
          • You need to put the js code or the referenced js file you wrote in @section scripts{}.
            • @section scripts{
              <script src="~/Scripts/jquery.validate.min.js"></script>
                  <script src="~/Scripts/jquery.validate.unobtrusive.min.js"></script> <script> //js code </script> }
      2. If your page is not using layout view
        1. You only need to quote the jquery file on the page.
        2. <script src="~/Scripts/jquery-3.4.1.min.js"></script>
          <script>
              //js code
          </script>
    3. If it is another error message, you can give the error message so that we can better help you.
    4. According to the code you provide and your description, you can use MVC client validation.
      1. You need to reference the jquery.validate.min.js and jquery.validate.unobtrusive.min.js files.
      2. You need to validate the model using data annotation validator properties.
      3. I will give you a simple example, you can refer to it to modify your code.

    Model

        public class UserValidation
        {
            [Key]
            [Required]
            public int ID { get; set; }
            [Required(ErrorMessage = "Name is Requirde")]
            public string  Name { get; set; }
            [Required(ErrorMessage = "Password is Requirde")]
            [RegularExpression(@"^[a-zA-Z0-9]{1,3}$",ErrorMessage = "PassWord can only be numbers and letters, and the length of the password is 1-3")]
            public string PassWord { get; set; }
            public string Other { get; set; }
        }

    Controller

            public ActionResult Index()
            {
                return View();
            }
            [HttpPost]
            public ActionResult getdata(UserValidation test)
            {
                if (ModelState.IsValid)
                {
                }
                return View();
            }

    View

    @model DailyMVCDemo.Models.UserValidation
    @using (Html.BeginForm("getdata", "UserValidation", FormMethod.Post))
    {
        @Html.DisplayNameFor(m => m.ID)
        @Html.TextBoxFor(m => m.ID)
        @Html.ValidationMessageFor(m => m.ID)<br />
        @Html.DisplayNameFor(m => m.Name)
        @Html.TextBoxFor(m => m.Name)
        @Html.ValidationMessageFor(m => m.Name)<br />
        @Html.DisplayNameFor(m => m.PassWord)
        @Html.TextBoxFor(m => m.PassWord)<br />
        @Html.ValidationMessageFor(m => m.PassWord)<br />
        @Html.DisplayNameFor(m => m.Other)
        @Html.TextBoxFor(m => m.Other)
        @Html.ValidationMessageFor(m => m.Other)<br />
        <button type="submit">submit</button>
    }
    @section scripts{
        <script src="~/Scripts/jquery.validate.min.js"></script>
        <script src="~/Scripts/jquery.validate.unobtrusive.min.js"></script>
    }

    Here is the result.

    Best Regards,

    YihuiSun

    Tuesday, September 15, 2020 9:43 AM