I have recently purchased and am using Bootstrap FormValidation from http://formvalidation.io/ and using the example on http://formvalidation.io/examples/requiring-at-least-one-field/ I am trying to set up my for the require EITHER an email or a phone number but I am not able to get the example to work correctly. No matter what I do I see an error message saying "You must enter at least one contact method" only under the Primary Email field.
If the FULL code would be helpful I can post but here are the relevant code snippets.
<div class="form-group">
<label class="control-label" for="primaryEmail">Primary Email</label>
<input type="text" class="form-control contactMethod" id="primaryEmail"
name="primaryEmail" value="" placeholder="Enter email">
</div>
<div class="form-group">
<label class="control-label" for="cPhone">Cell Phone</label>
<input type="text" class="form-control contactMethod" id="cPhone" name="cPhone"
value="" placeholder="Enter cell phone">
</div>
Validation section of the javascript
$('#form').formValidation({
framework: 'bootstrap',
icon: {
valid: 'glyphicon glyphicon-ok',
invalid: 'glyphicon glyphicon-remove',
validating: 'glyphicon glyphicon-refresh'
},
fields: {
cPhone: {
validators: {
phone: {
country: 'country',
message: 'The value is not valid %s phone number'
}
}
},
primaryEmail: {
validators: {
emailAddress: {
message: 'The value is not a valid email address'
}
}
},
secondaryEmail: {
validators: {
emailAddress: {
message: 'The value is not a valid email address'
}
}
},
wPhone: {
validators: {
phone: {
country: 'country',
message: 'The value is not valid %s phone number'
}
}
},
contact : {
selector: '.contactMethod',
validators: {
callback: {
message: 'You must enter at least one contact method',
callback: function(value, validator, $field) {
var isEmpty = true,
// Get the list of fields
$fields = validator.getFieldElements('contact');
console.log($fields);
for (var i = 0; i < $fields.length; i++) {
if ($fields.eq(i).val() !== '') {
isEmpty = false;
break;
}
}
if (!isEmpty) {
// Update the status of callback validator for all fields
validator.updateStatus('contact', validator.STATUS_VALID, 'callback');
return true;
}
return false;
}
}
}
}
}
});
In the exmaple the line $fields = validator.getFieldElements('cm');
has cm replaced with email but it did appear to be anything but an arbitrary label. But it maybe more than a label that matches the validator.updateStatus('cm', validator.STATUS_VALID, 'callback');
line. cm has been changed to contact
All other validations seem to be working on the page.
UPDATE:
if I dump $fields
to the console right after $fields = validator.getFieldElements('cm');
I get "input=([name="primaryEmail"])"
I would have thought it would have been an object with both primaryEmail and cPhone.
UPDATE 5-18-15 first the HTML then the scripts. I have made things even more difficult by adding a thrid option into the mix but the use can use a cell phone, work phone or primary email as a contact method one one is required.
<div class="form-group">
<label class="control-label" for="primaryEmail">Primary Email <i class="fa fa-asterisk text-warning"></i></label>
<input type="text" class="form-control contactMethod" id="primaryEmail" name="primaryEmail" value="" placeholder="Enter email" data-fv-field="contactMethod">
</div>
<div class="form-group">
<label class="control-label phoneMask" for="cPhone">Cell Phone <i class="fa fa-asterisk text-warning"></i></label>
<input type="text" class="form-control contactMethod" id="cPhone" name="cPhone" value="" placeholder="Enter cell phone" data-fv-field="contactMethod">
</div>
<div class="form-group">
<label class="control-label phoneMask" for="wPhone">Work Phone <i class="fa fa-asterisk text-warning"></i></label>
<input type="text" class="form-control contactMethod" id="wPhone" name="wPhone" value="" placeholder="Enter work phone" data-fv-field="contactMethod">
</div>
I have tried several scripts :
Here is the one that most closely resembled the example on http://formvalidation.io/examples/requiring-at-least-one-field/
$('#leadForm').formValidation({
framework: 'bootstrap',
icon: {
valid: 'glyphicon glyphicon-ok',
invalid: 'glyphicon glyphicon-remove',
validating: 'glyphicon glyphicon-refresh'
},
fields: {
fName: {
validators: {
notEmpty: {
message: 'The first name is required'
},
stringLength: {
min: 2,
max: 30,
message: 'The first name must be more than 2 and less than 30 characters long'
}
}
},
lName: {
validators: {
notEmpty: {
message: 'The last name is required'
},
stringLength: {
min: 2,
max: 30,
message: 'The last name must be more than 2 and less than 30 characters long'
}
}
},
secondaryEmail: {
validators: {
emailAddress: {
message: 'The value is not a valid email address'
}
}
},
contactMethod: {
selector: '.contactMethod',
validators: {
callback: function(value, validator, $field) {
var isEmpty = true,
isValid = false,
returnIsValid = false,
// Get the list of fields
$fields = validator.getFieldElements('contactMethod'),
fv = $('#leadForm').data('formValidation');
for (var i = 0; i < $fields.length; i++) {
thisField = $fields[i].id;
// trim value of field
thisVal = jQuery.trim($('#'+thisField).val());
if(thisVal.length == 0){
console.log('empty '+thisField);
fv.updateStatus(thisField, 'INVALID', 'callback').updateMessage(thisField,validator,'test');
} else {
if(thisField == 'cPhone' || thisField == 'wPhone'){
console.log('validating '+thisField);
} else if(thisField == 'primaryEmail'){
console.log('validating '+thisField);
}
}
if ($fields.eq(i).val() !== '') {
isEmpty = false;
break;
}
}
if (!isEmpty) {
// Update the status of callback validator for all fields
validator.updateStatus('contactMethod', validator.STATUS_VALID, 'callback');
returnIsValid = false;
} else {
}
return returnIsValid;
}
}
}
}
}).on('success.form.fv', function(e) {
e.preventDefault();
var $form = $(e.target),
fv = $form.data('formValidation');
// console.log($form.serialize());
// console.log(fv);
$.ajax({
type: 'post',
url: 'api/add.jsp?surveyId='+cfg['lead.surveyID'],
data: $form.serialize(),
dataType: 'json',
async: false,
success: function(result){
console.log(result);
}
}
});
});
This one more closely resembles what @Béranger had suggested. It actually comes very close but since so much of it is on the keyup it isn't triggered on the click of the submit button. I have tried adding.
$('#leadForm').formValidation({
framework: 'bootstrap',
icon: {
valid: 'glyphicon glyphicon-ok',
invalid: 'glyphicon glyphicon-remove',
validating: 'glyphicon glyphicon-refresh'
},
fields: {
primaryEmail: {
validators: {
notEmpty: {
message: 'You must include at least one contact method'
},
emailAddress: {
message: 'The value is not a valid email address'
}
}
},
cPhone: {
validators: {
notEmpty: {
message: 'You must include at least one contact method'
},
phone: {
country: 'country',
message: 'The value is not valid %s phone number'
}
}
},
wPhone: {
validators: {
notEmpty: {
message: 'You must include at least one contact method'
},
phone: {
country: 'country',
message: 'The value is not valid %s phone number'
}
}
}
}
})
.on('keyup', '[name="primaryEmail"], [name="cPhone"], [name="wPhone"]', function(e) {
var cPhoneIsEmpty = jQuery.trim($('#leadForm').find('[name="cPhone"]').val()) === '',
wPhoneIsEmpty = jQuery.trim($('#leadForm').find('[name="wPhone"]').val()) === '',
primaryEmailIsEmpty = jQuery.trim($('#leadForm').find('[name="primaryEmail"]').val()) === '',
fv = $('#leadForm').data('formValidation');
var cPhoneIsValid = fv.isValidField('cPhone') === true ? true : false;
var wPhoneIsValid = fv.isValidField('wPhone') === true ? true : false;
var primaryEmailIsValid = fv.isValidField('primaryEmail') === true ? true : false;
switch ($(this).attr('name')) {
// User is focusing the primaryEmail field
case 'primaryEmail':
fv.enableFieldValidators('cPhone', primaryEmailIsEmpty).revalidateField('cPhone');
fv.enableFieldValidators('wPhone', primaryEmailIsEmpty).revalidateField('wPhone');
break;
// User is focusing the cPhone field
case 'cPhone':
fv.enableFieldValidators('primaryEmail', cPhoneIsEmpty).revalidateField('primaryEmail');
fv.enableFieldValidators('wPhone', cPhoneIsEmpty).revalidateField('wPhone');
break;
// User is focusing the cPhone field
case 'wPhone':
fv.enableFieldValidators('primaryEmail', wPhoneIsEmpty).revalidateField('primaryEmail');
fv.enableFieldValidators('cPhone', wPhoneIsEmpty).revalidateField('cPhone');
break;
default:
break;
}
// if( (cPhoneIsValid || wPhoneIsValid || primaryEmailIsValid)){
// fv.enableFieldValidators('primaryEmail', false, 'notEmpty').revalidateField('primaryEmail');
// fv.enableFieldValidators('cPhone', false, 'notEmpty').revalidateField('cPhone');
// fv.enableFieldValidators('wPhone', false, 'notEmpty').revalidateField('cPhone');
// } else {
// fv.enableFieldValidators('primaryEmail', true).revalidateField('primaryEmail');
// fv.enableFieldValidators('cPhone', true).revalidateField('cPhone');
// fv.enableFieldValidators('wPhone', true).revalidateField('cPhone');
// }
// fv.enableFieldValidators('primaryEmail', true);
// fv.enableFieldValidators('cPhone', true);
// fv.enableFieldValidators('wPhone', true);
}).on('success.form.fv', function(e) {
e.preventDefault();
// console.log('submit here');
var $form = $(e.target),
fv = $form.data('formValidation');
// console.log($form.serialize());
// console.log(fv);
$.ajax({
type: 'post',
url: 'api/add.jsp?surveyId='+cfg['lead.surveyID'],
data: $form.serialize(),
dataType: 'json',
async: false,
success: function(result){
console.log(result);
}
});
});
if one field in the form is filled,all other fields must be filled or if none of the fields are filled then no need of checking validations. Iam using a method focus to add validations. once selecting a field,all fields are required validation executing.
In Angular, creating a custom validator is as simple as creating another function. The only thing you need to keep in mind is that it takes one input parameter of type AbstractControl and it returns an object of a key-value pair if the validation fails.
HTML form validation is applied via CSS’s two pseudo-classes, :invalid and :valid. It applies to <input>, <select>, and <textarea> elements. Bootstrap scopes the :invalid and :valid styles to their parent .was-validated class, usually applied to the <form>.
Bootstrap scopes the :invalid and :valid styles to their parent .was-validated class, usually applied to the <form>. Otherwise, any required field without a value shows up as invalid when a page is loaded.
Our example forms show native textual <input> s above, but form validation styles are available for our custom form controls, as well.
Add either .was-validated or .needs-validation to the <form> element, depending on whether you want to provide validation feedback before or after submitting the form. The input fields will have a green (valid) or red (invalid) border to indicate what's missing in the form.
You can disable the second validation and make it enabled only when the first is wrong :
take a look at this link
<form id="profileForm" method="post">
<p>Please provide one of these information:</p>
<div class="form-group">
<label class="control-label">Social Security Number</label>
<input type="text" class="form-control" name="ssn" />
</div>
<div class="form-group text-center">— Or —</div>
<div class="form-group">
<label class="control-label">Driver's License Number</label>
<input type="text" class="form-control" name="driverLicense" />
</div>
<div class="form-group">
<button type="submit" class="btn btn-default">Submit</button>
</div>
</form>
<script>
$(document).ready(function() {
$('#profileForm')
.formValidation({
framework: 'bootstrap',
icon: {
valid: 'glyphicon glyphicon-ok',
invalid: 'glyphicon glyphicon-remove',
validating: 'glyphicon glyphicon-refresh'
},
fields: {
ssn: {
validators: {
notEmpty: {
message: 'Please provide the Social Security number'
},
regexp: {
regexp: /^(?!(000|666|9))\d{3}(?!00)\d{2}(?!0000)\d{4}$/,
message: 'The format of your SSN is invalid. It should be XXXXXXXXX with no dashes'
}
}
},
driverLicense: {
// Disable validators
enabled: false,
validators: {
notEmpty: {
message: 'Or the Drivers License number'
},
stringLength: {
min: 8,
max: 20,
message: 'The Drivers License number must be more than 8 and less than 20 characters long'
}
}
}
}
})
.on('keyup', '[name="ssn"], [name="driverLicense"]', function(e) {
var driverLicense = $('#profileForm').find('[name="driverLicense"]').val(),
ssn = $('#profileForm').find('[name="ssn"]').val(),
fv = $('#profileForm').data('formValidation');
switch ($(this).attr('name')) {
// User is focusing the ssn field
case 'ssn':
fv.enableFieldValidators('driverLicense', ssn === '').revalidateField('driverLicense');
if (ssn && fv.getOptions('ssn', null, 'enabled') === false) {
fv.enableFieldValidators('ssn', true).revalidateField('ssn');
} else if (ssn === '' && driverLicense !== '') {
fv.enableFieldValidators('ssn', false).revalidateField('ssn');
}
break;
// User is focusing the drivers license field
case 'driverLicense':
if (driverLicense === '') {
fv.enableFieldValidators('ssn', true).revalidateField('ssn');
} else if (ssn === '') {
fv.enableFieldValidators('ssn', false).revalidateField('ssn');
}
if (driverLicense && ssn === '' && fv.getOptions('driverLicense', null, 'enabled') === false) {
fv.enableFieldValidators('driverLicense', true).revalidateField('driverLicense');
}
break;
default:
break;
}
});
});
</script>
Reading the documentation of getFieldElements it is not an arbitrary label. It is the name of the element you wish to select. It returns a jQuery[] so I am guessing underneath the hood it is just doing an attribute selection similar to $( "input[name*='elementname']" );
I am basing that on the fact that in their example both fields contain 'email' and that is the name they are selecting on. Granted that does not explain why 'cm' has anything returned but they may be doing some other magic.
I would suspect that if you changed the names of your contact fields to something like 'phoneContact' and 'emailContact'
<div class="form-group">
<label class="control-label" for="emailContact">Primary Email</label>
<input type="text" class="form-control contactMethod" id="primaryEmail"
name="emailContact" value="" placeholder="Enter email">
</div>
<div class="form-group">
<label class="control-label" for="phoneContact">Cell Phone</label>
<input type="text" class="form-control contactMethod" id="cPhone" name="phoneContact"
value="" placeholder="Enter cell phone">
</div>
And then changed your field name to 'contact' you should see both fields.
//...
$fields = validator.getFieldElements('contact');
//..
validator.updateStatus('contact', validator.STATUS_VALID, 'callback');
Since you're using different field types you can't group the validation using same validators for all input fields like they did in the example. Creating a custom validator for each field using callback then updating all fields to valid when input is detected worked for me. See javascript part of code...
<script>
$(document).ready(function() {
$('#profileForm').formValidation({
framework: 'bootstrap',
icon: {
valid: 'glyphicon glyphicon-ok',
invalid: 'glyphicon glyphicon-remove',
validating: 'glyphicon glyphicon-refresh'
},
fields: {
primaryEmail: {
validators: {
callback: {
message: 'You must enter atleast one field ',
callback: function(value, validator, $field) {
if ($("input[name=primaryEmail]").val()) {
// Update the status of callback validator for all fields
validator.updateStatus('primaryEmail', validator.STATUS_VALID, 'callback');
validator.updateStatus('cPhone', validator.STATUS_VALID, 'callback');
return true;
}
return false;
}
},
emailAddress: {
message: 'The value is not a valid email address'
}
}
},//primaryEmail
cPhone : {
validators : {
callback: {
message: 'You must enter atleast one field',
callback: function(value, validator, $field) {
if ($("input[name=cPhone]").val()) {
// Update the status of callback validator for all fields
validator.updateStatus('primaryEmail', validator.STATUS_VALID, 'callback');
validator.updateStatus('cPhone', validator.STATUS_VALID, 'callback');
return true;
}
return false;
}
},
stringLength: {
min: 8,
message: "Please enter a contact number with 8 digits"
}
}
}//cPhone
}//fields
});
$('#profileForm').formValidation().on("success.form.bv", function (e) {
e.preventDefault();
alert('success');
$('.form-group').addClass("hidden");
});
});
</script>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With