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:
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
2
Answers
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:or this:
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:
Here’s a demo in Stack Snippets
Every
input
element that you need validated must contain a uniquename
attribute or the jQuery Validate plugin will ignore it.In the case of
radio
andcheckbox
elements, they share the samename
when they are part of a single input group…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 includingradio
),select
, andtextarea
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.