0

I have a PHP data entry page using a Bootstrap Wizard, and now am adding some data validation with jQuery Validate.

I have got the basic type fields to work properly, simply with "required" attribute.

But the last 9 tabs of the wizard are "btn-groups" which are not input types, so dont have this functionality. To get around a previous issue (and something that seems quite common to be honest) I added a "hidden" input field, and when a btn-group is changed, it sets the value of the hidden field.

But I am unable to perform validation against either the btn-groups or the hidden fields.

I saw the first solution to the following thread:

Similar Issue

This seems perfect. However when I plug it into my site, I cannot get the wizard to move from the page before of the wizard (i.e. tab 1) where the first hidden field exists (i.e. tab 2), if i dont pre-set the initial value (which then breaks the validation test!).

Currently, the code looks like below. In the first score tab, "hole1score", I have removed the 'value="0"' and added "required", so it gets the validation. All other tabs have the original syntax with pre-set the value to 0. If I can get past this page in the wizard, I will apply it to all.

<head>
    <!-- THERE IS SOME MORE CODE ABOVE, BUT JUST THE USUAL IMPORTING FILES -->

    <!-- Include jQuery Validate -->
    <script src="../js/jquery.validate.min.js"></script>

    <!-- Include Bootstrap Wizard -->
    <script src="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap-wizard/1.2/jquery.bootstrap.wizard.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/prettify/r298/prettify.min.js"></script>
    <script>
        $(document).ready(function() {
            var $validator = $("#entry_form").validate({
              ignore: [],
              rules: {
                firstname: {
                  required: true,
                }
              },
              messages: {
                hcap: "A number is required"
              }
            }); 

            $('#rootwizard').bootstrapWizard({
                'tabClass': 'nav nav-pills',
                'onNext': function(tab, navigation, index) {
                    //if(index>=2) {
                    //  //alert($('#hole1score').val());
                    //}

                    var $valid = $("#entry_form").valid();
                    if(!$valid) {
                        $validator.focusInvalid();
                        return false;
                    }
                }
            });



            $('#rootwizard').bootstrapWizard({onTabShow: function(tab, navigation, index) {
                var $total = navigation.find('li').length;
                var $current = index+1;
                var $percent = ($current/$total) * 100;

                $('#rootwizard .progress-bar').css({width:$percent+'%'});

                // If it's the last tab then hide the last button and show the finish instead
                if($current >= $total) {
                    $('#rootwizard').find('.pager .next').hide();
                    $('#rootwizard').find('.pager .finish').show();
                    $('#rootwizard').find('.pager .finish').removeClass('disabled');
                } else {
                    $('#rootwizard').find('.pager .next').show();
                    $('#rootwizard').find('.pager .finish').hide();
                }
            }});

            $(".btn-group :input").change(function() {
                $('input[name="' + $(this).parent().parent().attr('id') + '"]').val($(this).val());
            }); 
        });
    </script>
    <script>
      function selectPlayer(myForm)
      {
        var jplayerid = myForm.playerlist.options[myForm.playerlist.selectedIndex].value;
        var jplayername = myForm.playerlist.options[myForm.playerlist.selectedIndex].text;
        var jplayernames = jplayername.split(" ");
        myForm.firstname.value = jplayernames[0];
        myForm.lastname.value = jplayernames[1];
      }
    </script>
</head>

<body>

            <div id="rootwizard">

                <div class="row">
                    <div class="col-xs-12 col-sm-12">
                        <div class="navbar">
                            <div class="navbar-inner">
                                <ul>
                                    <li><a href="#tab1" data-toggle="tab">Info</a></li>
                                    <li><a href="#tab2" data-toggle="tab">1st</a></li>
                                    <li><a href="#tab3" data-toggle="tab">2nd</a></li>
                                    <li><a href="#tab4" data-toggle="tab">3rd</a></li>
                                    <li><a href="#tab5" data-toggle="tab">4th</a></li>
                                    <li><a href="#tab6" data-toggle="tab">5th</a></li>
                                    <li><a href="#tab7" data-toggle="tab">6th</a></li>
                                    <li><a href="#tab8" data-toggle="tab">7th</a></li>
                                    <li><a href="#tab9" data-toggle="tab">8th</a></li>
                                    <li><a href="#tab10" data-toggle="tab">9th</a></li>
                                </ul>
                            </div>
                        </div>
                    </div>
                </div>

                <div class="row">
                    <div class="col-xs-12">
                        <div id="bar" class="progress progress-striped active">
                            <div class="progress-bar" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" style="width: 0%;"></div>
                        </div>  
                    </div>              
                </div>

                <form action="" method="post" class="form" role="form" name="entry_form" id="entry_form" autcomplete="on">
                    <div class="tab-content">
                        <div class="tab-pane" id="tab1">

                            <div class="row">
                                <div class="col-xs-12">
                                    <label for="">Name</label>
                                </div>
                            </div>

                            <div class="row">
                                <div class="col-xs-12 col-sm-6 col-md-4">
                                    <select class="form-control" name="playerlist" id="playerlist" onchange="selectPlayer(this.form)">
                                        <option value="" selected>Select Name or Type New Name</option>
                                        <?php
                                            $player_list = get_players();
                                            echo $player_list;
                                        ?>
                                    </select>
                                    <br>                                    
                                </div>
                            </div>

                            <div class="row">
                                <div class="col-xs-6 col-sm-3 col-md-2">
                                    <input class="form-control" id="firstname" name="firstname" type="text" required />
                                </div>
                                <div class="col-xs-6 col-sm-3 col-md-2">
                                    <input class="form-control" id="lastname" name="lastname" type="text" required />
                                </div>
                            </div>

                            <div class="row">
                                <div class="col-xs-12">
                                    <br>
                                    <label for="">HCap and Nine</label>
                                </div>
                            </div>

                            <div class="row">
                                <div class="col-xs-6 col-sm-3 col-md-2">
                                    <input class="form-control" name="hcap" placeholder="HCap" type="number" required />
                                </div>
                                <div class="col-xs-6 col-sm-3 col-md-2">
                                    <select name="nine" class="form-control" required>
                                        <option value="">Select Nine</option>
                                        <option value="1">Low</option>
                                        <option value="2">Middle</option>
                                        <option value="3">High</option>
                                    </select>
                                </div>
                            </div>

                            <div class="row">
                                <div class="col-xs-12">
                                    <br>
                                    <label for="">Date Played</label>
                                </div>
                            </div>

                            <div class="row">
                                <div class="col-xs-12 col-sm-6 col-md-4">
                                    <div class="col-xs-4">
                                        <select class="form-control" name="dateday">
                                            <?php
                                                for ($x = 1; $x <= 31; $x++) {
                                                    if ($todayday==$x){
                                                        $dynday .= '<option value='.$x.' selected>'.$x.'</option>';
                                                    } else {
                                                        $dynday .= '<option value='.$x.'>'.$x.'</option>';
                                                    }
                                                ;
                                                }
                                                echo $dynday;
                                            ?>
                                        </select>
                                    </div>
                                    <div class="col-xs-4">
                                        <select class="form-control" name="datemonth">
                                            <?php
                                                for ($x = 1; $x <= 12; $x++) {
                                                    if ($todaymonth==$x){
                                                        $dynmonth .= '<option value='.$x.' selected>'.$x.'</option>';
                                                    } else {
                                                        $dynmonth .= '<option value='.$x.'>'.$x.'</option>';
                                                    }
                                                };
                                                echo $dynmonth;
                                            ?>
                                        </select>
                                    </div>
                                    <div class="col-xs-4">
                                        <select class="form-control" name="dateyear">
                                            <?php
                                                $dynyear = '<option value='.$todayyear.' selected>'.$todayyear.'</option>';
                                                echo $dynyear;
                                            ?>
                                        </select>
                                        <br>
                                    </div>
                                </div>
                            </div>                              

                        </div>

                        <div class="tab-pane" id="tab2">

                            <div class="row">
                                <div class="col-xs-12">
                                    <label for="">HOLE 1 Gross Score</label>                                        
                                </div>
                            </div>

                            <div class="row">
                                <div class="col-xs-12 col-sm-9">
                                    <div class="btn-group btn-group-justified" data-toggle="buttons" id="hole1score">
                                        <label class="btn btn-primary btn-responsive">
                                            <input type="radio" autocomplete="off" value="0"> Blob
                                        </label>
                                        <label class="btn btn-primary btn-responsive">
                                            <input type="radio" autocomplete="off" value="2">2
                                        </label>
                                        <label class="btn btn-primary btn-responsive">
                                            <input type="radio" autocomplete="off" value="3">3
                                        </label>
                                        <label class="btn btn-primary btn-responsive">
                                            <input type="radio" autocomplete="off" value="4">4
                                        </label>
                                        <label class="btn btn-primary btn-responsive">
                                            <input type="radio" autocomplete="off" value="5">5
                                        </label>
                                        <label class="btn btn-primary btn-responsive">
                                            <input type="radio" autocomplete="off" value="6">6
                                        </label>
                                        <label class="btn btn-primary btn-responsive">
                                            <input type="radio" autocomplete="off" value="7">7
                                        </label>
                                        <label class="btn btn-primary btn-responsive">
                                            <input type="radio" autocomplete="off" value="8">8
                                        </label>
                                        <input type="hidden" name="hole1score" required>
                                    </div>

                                </div>                              
                            </div>
                        </div>

                        <div class="tab-pane" id="tab3">

                            <div class="row">
                                <div class="col-xs-12">
                                    <label for="">HOLE 2 Gross Score</label>                                        
                                </div>
                            </div>

                            <div class="row">
                                <div class="col-xs-12 col-sm-9">
                                    <div class="btn-group btn-group-justified" data-toggle="buttons" id="hole2score">
                                        <label class="btn btn-primary btn-responsive">
                                            <input type="radio" autocomplete="off" value="0"> Blob
                                        </label>
                                        <label class="btn btn-primary btn-responsive">
                                            <input type="radio" autocomplete="off" value="2">2
                                        </label>
                                        <label class="btn btn-primary btn-responsive">
                                            <input type="radio" autocomplete="off" value="3">3
                                        </label>
                                        <label class="btn btn-primary btn-responsive">
                                            <input type="radio" autocomplete="off" value="4">4
                                        </label>
                                        <label class="btn btn-primary btn-responsive">
                                            <input type="radio" autocomplete="off" value="5">5
                                        </label>
                                        <label class="btn btn-primary btn-responsive">
                                            <input type="radio" autocomplete="off" value="6">6
                                        </label>
                                        <label class="btn btn-primary btn-responsive">
                                            <input type="radio" autocomplete="off" value="7">7
                                        </label>
                                        <label class="btn btn-primary btn-responsive">
                                            <input type="radio" autocomplete="off" value="8">8
                                        </label>
                                        <input type="hidden" name="hole2score" value="0">
                                    </div>

                                </div>                              
                            </div>
                        </div>

                            <div class="row">
                                <br>
                                <div class="col-xs-4 col-xs-offset-8 col-sm-2 col-sm-offset-7 col-md-offset-8">
                                    <button name="submit" class="btn btn-responsive btn-success" type="submit">Submit</button>                              
                                </div>
                            </div>
                        </div>

                        <div class="row">
                            <div class="col-xs-12">
                                <ul class="pager wizard">
                                    <li class="previous first"><a href="javascript:;">First</a></li>
                                    <li class="previous first" style="display:none;"><a href="#">First</a></li>
                                    <li class="previous"><a href="#">Previous</a></li>
                                    <li class="next last" style="display:none;"><a href="#">Last</a></li>
                                    <li class="next"><a href="#">Next</a></li>
                                    <li class="next finish" style="display:none;"><a href="javascript:;">Finish</a></li>
                                </ul>                               
                            </div>
                        </div>                          

                    </div>
                </form>


            </div>


</body>

Any help would be appreciated

Community
  • 1
  • 1
Dan Burt
  • 47
  • 1
  • 7
  • 1
    it would be easy to us if you provide a fiddle, your issue is clear but you have to help us to reproduce the issue , so we can find the issue . – J Santosh Sep 07 '15 at 10:58
  • first time creating a jsfiddle. its not working properly either, as the main content on the tabs isn't being displayed... https://jsfiddle.net/1d34kmhm/ – Dan Burt Sep 07 '15 at 12:06
  • 1
    Dan, welcome to Stack Overflow! There is way too much code here to represent a well composed question. You don't need the pager. You don't need a dependency on php. You don't need extra inputs. A good question isn't just a copy and paste dump of your own code, but should be trying to abstract out the nature of the problem and ask specifically about that, in a way that is easily reproducible for other people. Is it a lot of work? Sure! But you're asking other people to do work for you - and if you don't put in the effort, they'll have to **on top** of whatever it takes to fix the issue. – KyleMit Sep 08 '15 at 13:18

2 Answers2

4

The answer you linked to tried to solve the problem by listening for changes on buttons and populating a hidden field so that jQuery Validate had something to, well, validate. However, there's a simpler way to do this with native features that already exist in the library.

Bootstrap's button group is just a css wrapper for input[type=radio] to make it look pretty, and you can easily require radio buttons like this:

myRadioGroupName: { required: true}

or this:

<input type="radio" name="myRadioGroupName" value="0" required>  1
<input type="radio" name="myRadioGroupName" value="1" > 2
<input type="radio" name="myRadioGroupName" value="2" > 3

Note: Make sure you name all radio button groups. This ensures the radio buttons work properly in all browsers and that they post back a value with the form correctly.

Now jQuery Validate will automatically provide field validation messages for your group, but you'll probably want to move them outside of the radio button group. You can customize their placement like this:

<label for="myRadioGroupName" generated="true" class="error"></label>

Here's a demo in Stack Snippets

$(function() { 

  $("#test-form").validate({  
    ignore: [],
    rules: {
      first_name: { 
        required: true
      },
      hole1score: {
        required: true
      }
    }
  });
});
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.js"></script>
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.14.0/jquery.validate.js"></script>
<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>

<form id="test-form" action="post.php">
  <input type="text" name="first_name" class="form-control" required /><br/>
  
  <div class="btn-group btn-group-justified" data-toggle="buttons" id="hole1score">
    <label class="btn btn-primary btn-responsive">
      <input type="radio" autocomplete="off" name="hole1score" value="1" >1
    </label>
    <label class="btn btn-primary btn-responsive">
      <input type="radio" autocomplete="off" name="hole1score" value="2" >2
    </label>
    <label class="btn btn-primary btn-responsive">
      <input type="radio" autocomplete="off" name="hole1score" value="3">3
    </label>
  </div>

  <label for="hole1score" generated="true" class="error"></label><br/>
  
  <input type="submit" />
</form>
Community
  • 1
  • 1
KyleMit
  • 30,350
  • 66
  • 462
  • 664
  • Thanks Kyle, and apologies for the code dump... I tried putting your code into the site, removed the hidden field & the javascript helper with it. Validation works, but new formatting issues. Relates to the " – Dan Burt Sep 08 '15 at 17:56
  • @Dan, couple more Stack Overflow suggestions. Make sure you upvote people who took time to help you. Don't *just* comment "thanks!". Also, re-directing to your site is the ultimate code dump - and is likely to break over time, leading to very little value for future users. See [Something in my web site or project doesn't work. Can I just paste a link to it?](http://meta.stackoverflow.com/questions/125997/), where the overwhelming consensus is **No**. That said, the reason your buttons are scrunched is because you have your ` – KyleMit Sep 08 '15 at 18:24
  • upvote done. was just waiting to see what the final formatting issue was. thanks so much for being friendly and helpful, with the solution and site guidance! as you many others would have burned me for my conduct... ;o) – Dan Burt Sep 08 '15 at 19:25
2

Every input element that you need validated must contain a unique name attribute or the jQuery Validate plugin will ignore it.

<div class="row">
    <div class="col-xs-12 col-sm-9">
        <div class="btn-group btn-group-justified" data-toggle="buttons" id="hole2score">
            <label class="btn btn-primary btn-responsive">
                <input type="radio" autocomplete="off" value="0"> Blob
            </label>
            <label class="btn btn-primary btn-responsive">
                <input type="radio" autocomplete="off" value="2">2
            </label>....

In the case of radio and checkbox elements, they share the same name when they are part of a single input group...

<input type="radio" autocomplete="off" value="0" name="foo">
<input type="radio" autocomplete="off" value="2" name="foo">
<input type="radio" autocomplete="off" value="3" name="foo"> ....

I saw the first solution to the following thread: Similar Issue

That issue has virtually nothing to do with yours. They are trying to apply validation to a <button> element, which is not the kind of element the jQuery Validate plugin can handle. A <button> is also not a "data input" element, so not really sure why it would need to be validated in the first place.

jQuery Validate plugin can only validate input (certain various types including radio), select, and textarea elements. Since you want to validate <input type="radio"> elements, the plugin can handle these just fine, by default, without any special event handlers or hidden elements.

Community
  • 1
  • 1
Sparky
  • 98,165
  • 25
  • 199
  • 285