Bootstrap formvalidation.io пытается потребовать одно поле или другое
Недавно я приобрел и использую Bootstrap FormValidation из http://formvalidation.io/ и используя пример http://formvalidation.io/examples/requiring-at-least-one-field/ Я пытаюсь настроить мой запрос на запрос электронной почты или номер телефона, но я не могу заставить этот пример работать правильно. Независимо от того, что я делаю, я вижу сообщение об ошибке "Вы должны ввести хотя бы один метод контакта" только в поле Primary Email.
Если код FULL будет полезен, я могу опубликовать его, но здесь приведены соответствующие фрагменты кода.
<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>
Раздел валидации 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;
}
}
}
}
}
});
В exmaple строка $fields = validator.getFieldElements('cm');
заменена cm на электронная почта, но она выглядела как нечто, кроме произвольной метки. Но это может быть больше, чем метка, соответствующая строке validator.updateStatus('cm', validator.STATUS_VALID, 'callback');
. см было изменено на контакт
Все остальные проверки, похоже, работают на странице.
ОБНОВЛЕНИЕ:
если я дамп $fields
на консоль сразу после $fields = validator.getFieldElements('cm');
Я получаю "input=([name="primaryEmail"])"
Я бы подумал, что это был бы объект с как primaryEmail, так и cPhone.
ОБНОВЛЕНИЕ 5-18-15
сначала HTML, затем скрипты. Я усложнил ситуацию, добавив в микс вариант thrid, но использование может использовать мобильный телефон, рабочий телефон или первичный адрес электронной почты в качестве метода контакта, который требуется одному.
<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>
Я пробовал несколько скриптов:
Вот тот, который наиболее близко напоминает пример 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);
}
}
});
});
Это более похоже на то, что предложил @Béranger. Это на самом деле очень близко, но так как большая часть из них находится на клавиатуре, она не запускается при нажатии кнопки отправки. Я попытался добавить.
$('#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);
}
});
});
Ответы
Ответ 1
Считывая документацию getFieldElements, это не произвольная метка. Это имя элемента, который вы хотите выбрать. Он возвращает jQuery [], поэтому я угадываю под капотом, что он просто делает выбор атрибута, подобный $( "input[name*='elementname']" );
. Я основываю это на том факте, что в их примере оба поля содержат "email", и это имя, которое они выбирают на. Конечно, это не объясняет, почему "cm" имеет что-то, но они могут делать какую-то другую магию.
Я подозреваю, что если вы изменили имена своих полей контакта на что-то вроде "phoneContact" и "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>
И затем измените имя поля на "контакт", вы должны увидеть оба поля.
//...
$fields = validator.getFieldElements('contact');
//..
validator.updateStatus('contact', validator.STATUS_VALID, 'callback');
Ответ 2
Поскольку вы используете разные типы полей, вы не можете группировать проверку с использованием тех же валидаторов для всех полей ввода, как это было в примере. Создание настраиваемого валидатора для каждого поля с использованием обратного вызова, а затем обновление всех полей до действительных, когда вход обнаружен для меня. См. Javascript часть кода...
<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>
Ответ 3
Вы можете отключить вторую проверку и включить ее только тогда, когда первое неверно:
взгляните на эту ссылку
<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 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>
Ответ 4
Я не уверен, но я думаю, что "email" в getFieldElements не является произвольным, но на самом деле это имя поля "группа" (сразу после fields: {
).
Какое имя вашей группы? Это cm
?
Можете ли вы разместить весь <script>
?
Ответ 5
После проверки кода я обнаружил, что вам не хватает Атрибут.
Ниже приведен допустимый HTML
<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" data-fv-field="contact" />
</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" data-fv-field="contact" />
</div>
Вам не хватало атрибута data-fv-field
Ответ 6
Как @Sen k
сказал в своем ответе:
Поскольку вы используете разные типы полей, вы не можете группировать проверку с использованием тех же валидаторов для всех полей ввода...
Простое решение, вы можете использовать событие success.field.fv
, как описано в следующем коде:
$('#YourFormId').formValidation({
framework: 'bootstrap',
icon: {
valid: 'glyphicon glyphicon-ok',
invalid: 'glyphicon glyphicon-remove',
validating: 'glyphicon glyphicon-refresh'
},
fields: {
primaryEmail: {
validators: {
notEmpty: {},
emailAddress: {
message: 'The value is not a valid email address'
}
}
},
cPhone: {
validators: {
notEmpty: {},
phone: {
country: 'country',
message: 'The value is not valid %s phone number'
}
}
}
}
})
.on('success.field.fv', function(e, data) {
var primaryEmail = $('[name="primaryEmail"]'),
cPhone = $('[name="cPhone"]'),
validator = data.fv;
if (data.field === "primaryEmail" && cPhone.val() === '') {
// mark the cPhone field as valid if it empty & the
// primaryEmail field was valid.
validator.updateStatus('cPhone', validator.STATUS_VALID, null);
}
if (data.field === "cPhone" && primaryEmail.val() === '') {
// mark the primaryEmail field as valid if it empty & the
// cPhone field was valid.
validator.updateStatus('primaryEmail', validator.STATUS_VALID, null);
}
});
Примечание:
Я использовал валидатор notEmpty
, потому что валидаторы emailAdress
и phone
отмечают пустое поле как действительное.