Adding invalid icon to tab
By default, the fields in inactive tabs will not be validated because they are not
visible. In order to validate them, we need to use the excluded option:
excluded : [ ':disabled' ]
You should look at the
basic principles when integrating FormValidation
with other plugins
Assume that you want to add an icon to tab to indicate the valid or invalid tab. A tab is
called valid if all fields inside it are valid. Otherwise, if there is at least one
invalid field inside tab, the tab is invalid.
Firstly, we need to prepare the icon placed at the tab title:
< ul class = "nav nav-tabs" >
< li class = "active" >< a href = "#info-tab" data-toggle = "tab" > Tab title < i class = "fa" ></ i ></ a ></ li >
< li >< a href = "#address-tab" data-toggle = "tab" > Tab title < i class = "fa" ></ i ></ a ></ li >
</ ul >
Lastly, add success/error class to icon when the field is valid/invalid by triggering the
err.field.fv
and success.field.fv
events :
$ ( document ). ready ( function () {
$ ( '#accountForm' )
. formValidation ({
excluded : [ ':disabled' ],
...
})
// Called when a field is invalid
. on ( 'err.field.fv' , function ( e , data ) {
// data.element --> The field element
var $tabPane = data . element . parents ( '.tab-pane' ),
tabId = $tabPane . attr ( 'id' );
$ ( 'a[href="#' + tabId + '"][data-toggle="tab"]' )
. parent ()
. find ( 'i' )
. removeClass ( 'fa-check' )
. addClass ( 'fa-times' );
})
// Called when a field is valid
. on ( 'success.field.fv' , function ( e , data ) {
// data.fv --> The FormValidation instance
// data.element --> The field element
var $tabPane = data . element . parents ( '.tab-pane' ),
tabId = $tabPane . attr ( 'id' ),
$icon = $ ( 'a[href="#' + tabId + '"][data-toggle="tab"]' )
. parent ()
. find ( 'i' )
. removeClass ( 'fa-check fa-times' );
// Check if all fields in tab are valid
var isValidTab = data . fv . isValidContainer ( $tabPane );
if ( isValidTab !== null ) {
$icon . addClass ( isValidTab ? 'fa-check' : 'fa-times' );
}
});
});
< style type = "text/css" >
# accountForm {
margin-top : 15 px ;
}
</ style >
< ul class = "nav nav-tabs" >
< li class = "active" >< a href = "#info-tab" data-toggle = "tab" > Information < i class = "fa" ></ i ></ a ></ li >
< li >< a href = "#address-tab" data-toggle = "tab" > Address < i class = "fa" ></ i ></ a ></ li >
</ ul >
< form id = "accountForm" method = "post" class = "form-horizontal" >
< div class = "tab-content" >
< div class = "tab-pane active" id = "info-tab" >
< div class = "form-group" >
< label class = "col-xs-3 control-label" > Full name</ label >
< div class = "col-xs-5" >
< input type = "text" class = "form-control" name = "fullName" />
</ div >
</ div >
< div class = "form-group" >
< label class = "col-xs-3 control-label" > Company</ label >
< div class = "col-xs-5" >
< input type = "text" class = "form-control" name = "company" />
</ div >
</ div >
< div class = "form-group" >
< label class = "col-xs-3 control-label" > Job title</ label >
< div class = "col-xs-5" >
< input type = "text" class = "form-control" name = "jobTitle" />
</ div >
</ div >
</ div >
< div class = "tab-pane" id = "address-tab" >
< div class = "form-group" >
< label class = "col-xs-3 control-label" > Address</ label >
< div class = "col-xs-5" >
< input type = "text" class = "form-control" name = "address" />
</ div >
</ div >
< div class = "form-group" >
< label class = "col-xs-3 control-label" > City</ label >
< div class = "col-xs-5" >
< input type = "text" class = "form-control" name = "city" />
</ div >
</ div >
< div class = "form-group" >
< label class = "col-xs-3 control-label" > Country</ label >
< div class = "col-xs-5" >
< select class = "form-control" name = "country" >
< option value = "" > Select a country</ option >
< option value = "FR" > France</ option >
< option value = "DE" > Germany</ option >
< option value = "IT" > Italy</ option >
< option value = "JP" > Japan</ option >
< option value = "RU" > Russian</ option >
< option value = "US" > United State</ option >
< option value = "GB" > United Kingdom</ option >
< option value = "other" > Other</ option >
</ select >
</ div >
</ div >
</ div >
</ div >
< div class = "form-group" style = "margin-top: 15px;" >
< div class = "col-xs-5 col-xs-offset-3" >
< button type = "submit" class = "btn btn-default" > Validate</ button >
</ div >
</ div >
</ form >
< script >
$ ( document ). ready ( function () {
$ ( '#accountForm' )
. formValidation ({
framework : 'bootstrap' ,
// Only disabled elements are excluded
// The invisible elements belonging to inactive tabs must be validated
excluded : [ ':disabled' ],
icon : {
valid : 'glyphicon glyphicon-ok' ,
invalid : 'glyphicon glyphicon-remove' ,
validating : 'glyphicon glyphicon-refresh'
},
fields : {
fullName : {
validators : {
notEmpty : {
message : 'The full name is required'
}
}
},
company : {
validators : {
notEmpty : {
message : 'The company name is required'
}
}
},
address : {
validators : {
notEmpty : {
message : 'The address is required'
}
}
},
city : {
validators : {
notEmpty : {
message : 'The city is required'
}
}
}
}
})
// Called when a field is invalid
. on ( 'err.field.fv' , function ( e , data ) {
// data.element --> The field element
var $tabPane = data . element . parents ( '.tab-pane' ),
tabId = $tabPane . attr ( 'id' );
$ ( 'a[href="#' + tabId + '"][data-toggle="tab"]' )
. parent ()
. find ( 'i' )
. removeClass ( 'fa-check' )
. addClass ( 'fa-times' );
})
// Called when a field is valid
. on ( 'success.field.fv' , function ( e , data ) {
// data.fv --> The FormValidation instance
// data.element --> The field element
var $tabPane = data . element . parents ( '.tab-pane' ),
tabId = $tabPane . attr ( 'id' ),
$icon = $ ( 'a[href="#' + tabId + '"][data-toggle="tab"]' )
. parent ()
. find ( 'i' )
. removeClass ( 'fa-check fa-times' );
// Check if all fields in tab are valid
var isValidTab = data . fv . isValidContainer ( $tabPane );
if ( isValidTab !== null ) {
$icon . addClass ( isValidTab ? 'fa-check' : 'fa-times' );
}
});
});
</ script >
Activating tab containing invalid field
The following snippet shows how to activate the tab that contains the invalid field. It
uses the getInvalidFields() method to retrieve
the list of invalid fields, and from there, determine the tab containing the first
invalid one.
If that tab isn't active, then activate it and the associated <li>
element.
$ ( document ). ready ( function () {
$ ( '#accountForm' )
. formValidation ({
excluded : [ ':disabled' ],
...
})
. on ( 'err.field.fv' , function ( e , data ) {
// Get the first invalid field
var $invalidFields = data . fv . getInvalidFields (). eq ( 0 );
// Get the tab that contains the first invalid field
var $tabPane = $invalidFields . parents ( '.tab-pane' ),
invalidTabId = $tabPane . attr ( 'id' );
// If the tab is not active
if ( ! $tabPane . hasClass ( 'active' )) {
// Then activate it
...
// Focus on the field
$invalidFields . focus ();
}
});
});
< style type = "text/css" >
# accountForm {
margin-top : 15 px ;
}
</ style >
< ul class = "nav nav-tabs" >
< li class = "active" >< a href = "#info-tab" data-toggle = "tab" > Information < i class = "fa" ></ i ></ a ></ li >
< li >< a href = "#address-tab" data-toggle = "tab" > Address < i class = "fa" ></ i ></ a ></ li >
</ ul >
< form id = "accountForm" method = "post" class = "form-horizontal" >
< div class = "tab-content" >
< div class = "tab-pane active" id = "info-tab" >
< div class = "form-group" >
< label class = "col-xs-3 control-label" > Full name</ label >
< div class = "col-xs-5" >
< input type = "text" class = "form-control" name = "fullName" />
</ div >
</ div >
< div class = "form-group" >
< label class = "col-xs-3 control-label" > Company</ label >
< div class = "col-xs-5" >
< input type = "text" class = "form-control" name = "company" />
</ div >
</ div >
< div class = "form-group" >
< label class = "col-xs-3 control-label" > Job title</ label >
< div class = "col-xs-5" >
< input type = "text" class = "form-control" name = "jobTitle" />
</ div >
</ div >
</ div >
< div class = "tab-pane" id = "address-tab" >
< div class = "form-group" >
< label class = "col-xs-3 control-label" > Address</ label >
< div class = "col-xs-5" >
< input type = "text" class = "form-control" name = "address" />
</ div >
</ div >
< div class = "form-group" >
< label class = "col-xs-3 control-label" > City</ label >
< div class = "col-xs-5" >
< input type = "text" class = "form-control" name = "city" />
</ div >
</ div >
< div class = "form-group" >
< label class = "col-xs-3 control-label" > Country</ label >
< div class = "col-xs-5" >
< select class = "form-control" name = "country" >
< option value = "" > Select a country</ option >
< option value = "FR" > France</ option >
< option value = "DE" > Germany</ option >
< option value = "IT" > Italy</ option >
< option value = "JP" > Japan</ option >
< option value = "RU" > Russian</ option >
< option value = "US" > United State</ option >
< option value = "GB" > United Kingdom</ option >
< option value = "other" > Other</ option >
</ select >
</ div >
</ div >
</ div >
</ div >
< div class = "form-group" style = "margin-top: 15px;" >
< div class = "col-xs-5 col-xs-offset-3" >
< button type = "submit" class = "btn btn-default" > Validate</ button >
</ div >
</ div >
</ form >
< script >
$ ( document ). ready ( function () {
$ ( '#accountForm' )
. formValidation ({
framework : 'bootstrap' ,
// Only disabled elements are excluded
// The invisible elements belonging to inactive tabs must be validated
excluded : [ ':disabled' ],
icon : {
valid : 'glyphicon glyphicon-ok' ,
invalid : 'glyphicon glyphicon-remove' ,
validating : 'glyphicon glyphicon-refresh'
},
fields : {
fullName : {
validators : {
notEmpty : {
message : 'The full name is required'
}
}
},
company : {
validators : {
notEmpty : {
message : 'The company name is required'
}
}
},
address : {
validators : {
notEmpty : {
message : 'The address is required'
}
}
},
city : {
validators : {
notEmpty : {
message : 'The city is required'
}
}
}
}
})
. on ( 'err.field.fv' , function ( e , data ) {
// data.fv --> The FormValidation instance
// Get the first invalid field
var $invalidFields = data . fv . getInvalidFields (). eq ( 0 );
// Get the tab that contains the first invalid field
var $tabPane = $invalidFields . parents ( '.tab-pane' ),
invalidTabId = $tabPane . attr ( 'id' );
// If the tab is not active
if ( ! $tabPane . hasClass ( 'active' )) {
// Then activate it
$tabPane . parents ( '.tab-content' )
. find ( '.tab-pane' )
. each ( function ( index , tab ) {
var tabId = $ ( tab ). attr ( 'id' ),
$li = $ ( 'a[href="#' + tabId + '"][data-toggle="tab"]' ). parent ();
if ( tabId === invalidTabId ) {
// activate the tab pane
$ ( tab ). addClass ( 'active' );
// and the associated <li> element
$li . addClass ( 'active' );
} else {
$ ( tab ). removeClass ( 'active' );
$li . removeClass ( 'active' );
}
});
// Focus on the field
$invalidFields . focus ();
}
});
});
</ script >