如何关注必填或无效字段?
How to focus on required or invalid field?
我的表格很长,在某些情况下用户可能会漏掉一些必填字段。如果他们一直滚动到 Save
按钮并单击以发送表单数据,他们将不会看到错误消息。我想知道是否有一种方法可以触发 on focus
方法,将用户带到表单中的第一个字段,即 required
或 invalid
。这是我的表格示例:
var COMMON_FUNC = {};
$("#save").on("click", function() {
var frmObject = $(this).closest("form"),
frmDisabledFlds = frmObject.find(":input:disabled").prop("disabled", false),
frmData = frmObject.serialize();
frmDisabledFlds.prop("disabled", true);
if (COMMON_FUNC.verifyFields("new-record")) {
console.log('Send Form Data!');
}
});
COMMON_FUNC.verifyFields = function(containerID, includeInvisible) {
includeInvisible = includeInvisible || false;
let isValid = true;
const hdlMap = {
'valueMissing': "This field is required",
'patternMismatch': "This field is invalid",
'tooLong': "This field is too long",
'rangeOverflow': "This field is greater than allowed maximum",
'rangeUnderflow': "This field is less than allowed minimum",
'typeMismatch': "This field is mistyped"
};
const arrV = Object.keys(hdlMap);
$("#" + containerID).find("input,textarea,select").each(function() {
var curItem$ = $(this);
var errMsg = [];
var dispfld = curItem$.data("dispfld");
if (includeInvisible || curItem$.is(":visible")) {
if (curItem$[0].validity.valid) {
curItem$.removeClass("is-invalid");
return;
}
arrV.forEach(function(prop) {
if (curItem$[0].validity[prop]) {
if (prop === "patternMismatch" && dispfld) {
errMsg.push(dispfld);
} else {
errMsg.push(hdlMap[prop]);
}
}
});
if (errMsg.length) {
if (!curItem$.next().is(".invalid-feedback")) {
curItem$.after('<div class="invalid-feedback"></div>');
}
curItem$.addClass("is-invalid").next().text(errMsg.join(' and '));
isValid = false;
} else {
curItem$.removeClass("is-invalid");
}
}
});
return isValid;
};
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>
<div class="container">
<div class="card">
<div class="card-header">
<h4>New Record</h4>
</div>
<div class="card-body">
<form name="new-record" id="new-record" autocomplete="off">
<div class="form-group">
<label for="bldg_name">Building Name:</label>
<input class="form-control" type="text" name="bldg_name" id="bldg_name" value="" maxlength="500" placeholder="Enter the building name" required>
</div>
<div class="row">
<div class="col-12"><strong><u>Manager</u></strong></div>
</div>
<div class="form-row">
<div class="form-group col-6">
<label for="salutation">Salutation:</label>
<select class="custom-select browser-default" name="salutation" id="salutation">
<option value="">--Select Salutation--</option>
<option value="1">Mrs</option>
<option value="2">Ms</option>
<option value="3">Miss</option>
<option value="4">Mr</option>
</select>
</div>
<div class="form-group col-6">
<label for="title">Business Title:</label>
<select class="custom-select browser-default" name="title" id="title">
<option value="">--Select Title--</option>
<option value="1">Region Manager</option>
<option value="2">State Manager</option>
<option value="3">Building Manager</option>
</select>
</div>
</div>
<div class="form-row">
<div class="form-group col-6 required">
<label for="fname">First Name:</label>
<input class="form-control" type="text" name="fname" id="fname" value="" maxlength="20" placeholder="Enter First name" required>
</div>
<div class="form-group col-6 required">
<label for="lname">Last Name:</label>
<input class="form-control" type="text" name="lname" id="lname" value="" maxlength="30" placeholder="Enter Last name" required>
</div>
</div>
<div class="form-group required">
<label for="email">Email:</label>
<input class="form-control email" type="email" name="email" id="email" maxlength="50" placeholder="Enter Email address" required>
</div>
<div class="form-group row">
<div class="col-5 offset-2"><strong><u>Physical Address</u></strong></div>
<div class="col-5"><strong><u>Mailing Address</u></strong></div>
</div>
<div class="form-group row required">
<label for="address1" class="col-2 col-form-label">Address 1:</label>
<div class="col-5">
<input class="form-control physical" type="text" name="p_address1" id="p_address1" value="" placeholder="Enter Physical Address 1" maxlength="40" required>
</div>
<div class="col-5">
<input class="form-control mailing" type="text" name="m_address1" id="m_address1" value="" placeholder="Enter Mailing Address 1" maxlength="40" required>
</div>
</div>
<div class="form-group row">
<label for="address2" class="col-2 col-form-label">Address 2:</label>
<div class="col-5">
<input class="form-control physical" type="text" name="p_address2" id="p_address2" value="" placeholder="Enter Physical Address 2" maxlength="40">
</div>
<div class="col-5">
<input class="form-control mailing" type="text" name="m_address2" id="m_address2" value="" placeholder="Enter Mailing Address 2" maxlength="40">
</div>
</div>
<div class="form-group row">
<label for="address3" class="col-2 col-form-label">Address 3:</label>
<div class="col-5">
<input class="form-control physical" type="text" name="p_address3" id="p_address3" value="" placeholder="Enter Physical Address 3" maxlength="40">
</div>
<div class="col-5">
<input class="form-control mailing" type="text" name="m_address3" id="m_address3" value="" placeholder="Enter Mailing Address 3" maxlength="40">
</div>
</div>
<div class="form-group row">
<label for="address4" class="col-2 col-form-label">Address 4:</label>
<div class="col-5">
<input class="form-control physical" type="text" name="p_address4" id="p_address4" value="" placeholder="Enter Physical Address 4" maxlength="40">
</div>
<div class="col-5">
<input class="form-control mailing" type="text" name="m_address4" id="m_address4" value="" placeholder="Enter Mailing Address 4" maxlength="40">
</div>
</div>
<div class="form-group row required">
<label for="city" class="col-2 col-form-label">City:</label>
<div class="col-5">
<input class="form-control physical" type="text" name="p_city" id="p_city" value="" placeholder="Enter City" maxlength="25" required>
</div>
<div class="col-5">
<input class="form-control mailing" type="text" name="m_city" id="m_city" value="" placeholder="Enter City" maxlength="25" required>
</div>
</div>
<div class="form-group row required">
<label for="state" class="col-2 col-form-label">State:</label>
<div class="col-5">
<select class="custom-select browser-default physical" name="p_state" id="p_state" required>
<option value="">--Select State--</option>
<option value="az">Arizona</option>
<option value="ia">Iowa</option>
<option value="mo">Missouri</option>
<option value="ny">New York</option>
<option value="va">Virginia</option>
</select>
</div>
<div class="col-5">
<select class="custom-select browser-default mailing" name="m_state" id="m_state" required>
<option value="">--Select State--</option>
<option value="az">Arizona</option>
<option value="ia">Iowa</option>
<option value="mo">Missouri</option>
<option value="ny">New York</option>
<option value="va">Virginia</option>
</select>
</div>
</div>
<div class="form-group row required">
<label for="zip" class="col-2 col-form-label">Zip:</label>
<div class="col-5">
<input class="form-control physical" type="text" name="p_zip" id="p_zip" value="" pattern="(\d{5}([\-]\d{4})?)" data-dispfld="The required format is: xxxxx or xxxxx-xxxx" placeholder="Enter Zip Code, formatted: 99999 or 99999-9999" maxlength="10" required>
</div>
<div class="col-5">
<input class="form-control mailing" type="text" name="m_zip" id="m_zip" value="" pattern="(\d{5}([\-]\d{4})?)" data-dispfld="The required format is: xxxxx or xxxxx-xxxx" placeholder="Enter Zip Code, formatted: 99999 or 99999-9999" maxlength="10" required>
</div>
</div>
<div class="row">
<div class="col-12 text-center">
<button class="btn btn-outline-secondary" type="button" name="save" id="save">Save</button>
<button class="btn btn-outline-secondary" type="button" name="cancel" id="cancel">Cancel</button>
</div>
</div>
</form>
</div>
</div>
</div>
您可以 运行 此示例并在表单中输入除建筑物名称之外的所有信息。然后您可以单击“保存”按钮,您将无法在顶部看到错误消息。如果有人对如何处理此问题有建议,请告诉我。我愿意听到针对这种情况的不同解决方案。
您可以尝试像这样简单的操作(未经测试但应该有效):
document.getElementsByClassName('is-invalid')[0].scrollIntoView({ behavior: 'smooth' });
这会查找错误 class is-invalid
然后平滑滚动到找到的第一个
验证后添加此代码,如果发现错误。
DOM API 对元素具有 "focus" 功能,可以满足您的需求。
将所有有效元素推送到 invalidInputs 数组,然后您可以选择第一个无效元素并对该元素调用 .focus()。
var COMMON_FUNC = {};
$("#save").on("click", function() {
var frmObject = $(this).closest("form"),
frmDisabledFlds = frmObject.find(":input:disabled").prop("disabled", false),
frmData = frmObject.serialize();
frmDisabledFlds.prop("disabled", true);
if (COMMON_FUNC.verifyFields("new-record")) {
console.log('Send Form Data!');
}
});
COMMON_FUNC.verifyFields = function(containerID, includeInvisible) {
includeInvisible = includeInvisible || false;
let isValid = true;
const hdlMap = {
'valueMissing': "This field is required",
'patternMismatch': "This field is invalid",
'tooLong': "This field is too long",
'rangeOverflow': "This field is greater than allowed maximum",
'rangeUnderflow': "This field is less than allowed minimum",
'typeMismatch': "This field is mistyped"
};
const arrV = Object.keys(hdlMap);
// Create an array for the invalid fields.
const invalidInputs = [];
$("#" + containerID).find("input,textarea,select").each(function() {
var curItem$ = $(this);
var errMsg = [];
var dispfld = curItem$.data("dispfld");
if (includeInvisible || curItem$.is(":visible")) {
if (curItem$[0].validity.valid) {
curItem$.removeClass("is-invalid");
return;
}
arrV.forEach(function(prop) {
if (curItem$[0].validity[prop]) {
if (prop === "patternMismatch" && dispfld) {
errMsg.push(dispfld);
} else {
errMsg.push(hdlMap[prop]);
}
}
});
if (errMsg.length) {
if (!curItem$.next().is(".invalid-feedback")) {
curItem$.after('<div class="invalid-feedback"></div>');
}
curItem$.addClass("is-invalid").next().text(errMsg.join(' and '));
isValid = false;
//Push the invalid inputs onto the invalidInputs array.
invalidInputs.push(curItem$);
} else {
curItem$.removeClass("is-invalid");
}
}
});
// Focus on the first element that is invalid.
invalidInputs[0].focus();
return isValid;
};
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>
<div class="container">
<div class="card">
<div class="card-header">
<h4>New Record</h4>
</div>
<div class="card-body">
<form name="new-record" id="new-record" autocomplete="off">
<div class="form-group">
<label for="bldg_name">Building Name:</label>
<input class="form-control" type="text" name="bldg_name" id="bldg_name" value="" maxlength="500" placeholder="Enter the building name" required>
</div>
<div class="row">
<div class="col-12"><strong><u>Manager</u></strong></div>
</div>
<div class="form-row">
<div class="form-group col-6">
<label for="salutation">Salutation:</label>
<select class="custom-select browser-default" name="salutation" id="salutation">
<option value="">--Select Salutation--</option>
<option value="1">Mrs</option>
<option value="2">Ms</option>
<option value="3">Miss</option>
<option value="4">Mr</option>
</select>
</div>
<div class="form-group col-6">
<label for="title">Business Title:</label>
<select class="custom-select browser-default" name="title" id="title">
<option value="">--Select Title--</option>
<option value="1">Region Manager</option>
<option value="2">State Manager</option>
<option value="3">Building Manager</option>
</select>
</div>
</div>
<div class="form-row">
<div class="form-group col-6 required">
<label for="fname">First Name:</label>
<input class="form-control" type="text" name="fname" id="fname" value="" maxlength="20" placeholder="Enter First name" required>
</div>
<div class="form-group col-6 required">
<label for="lname">Last Name:</label>
<input class="form-control" type="text" name="lname" id="lname" value="" maxlength="30" placeholder="Enter Last name" required>
</div>
</div>
<div class="form-group required">
<label for="email">Email:</label>
<input class="form-control email" type="email" name="email" id="email" maxlength="50" placeholder="Enter Email address" required>
</div>
<div class="form-group row">
<div class="col-5 offset-2"><strong><u>Physical Address</u></strong></div>
<div class="col-5"><strong><u>Mailing Address</u></strong></div>
</div>
<div class="form-group row required">
<label for="address1" class="col-2 col-form-label">Address 1:</label>
<div class="col-5">
<input class="form-control physical" type="text" name="p_address1" id="p_address1" value="" placeholder="Enter Physical Address 1" maxlength="40" required>
</div>
<div class="col-5">
<input class="form-control mailing" type="text" name="m_address1" id="m_address1" value="" placeholder="Enter Mailing Address 1" maxlength="40" required>
</div>
</div>
<div class="form-group row">
<label for="address2" class="col-2 col-form-label">Address 2:</label>
<div class="col-5">
<input class="form-control physical" type="text" name="p_address2" id="p_address2" value="" placeholder="Enter Physical Address 2" maxlength="40">
</div>
<div class="col-5">
<input class="form-control mailing" type="text" name="m_address2" id="m_address2" value="" placeholder="Enter Mailing Address 2" maxlength="40">
</div>
</div>
<div class="form-group row">
<label for="address3" class="col-2 col-form-label">Address 3:</label>
<div class="col-5">
<input class="form-control physical" type="text" name="p_address3" id="p_address3" value="" placeholder="Enter Physical Address 3" maxlength="40">
</div>
<div class="col-5">
<input class="form-control mailing" type="text" name="m_address3" id="m_address3" value="" placeholder="Enter Mailing Address 3" maxlength="40">
</div>
</div>
<div class="form-group row">
<label for="address4" class="col-2 col-form-label">Address 4:</label>
<div class="col-5">
<input class="form-control physical" type="text" name="p_address4" id="p_address4" value="" placeholder="Enter Physical Address 4" maxlength="40">
</div>
<div class="col-5">
<input class="form-control mailing" type="text" name="m_address4" id="m_address4" value="" placeholder="Enter Mailing Address 4" maxlength="40">
</div>
</div>
<div class="form-group row required">
<label for="city" class="col-2 col-form-label">City:</label>
<div class="col-5">
<input class="form-control physical" type="text" name="p_city" id="p_city" value="" placeholder="Enter City" maxlength="25" required>
</div>
<div class="col-5">
<input class="form-control mailing" type="text" name="m_city" id="m_city" value="" placeholder="Enter City" maxlength="25" required>
</div>
</div>
<div class="form-group row required">
<label for="state" class="col-2 col-form-label">State:</label>
<div class="col-5">
<select class="custom-select browser-default physical" name="p_state" id="p_state" required>
<option value="">--Select State--</option>
<option value="az">Arizona</option>
<option value="ia">Iowa</option>
<option value="mo">Missouri</option>
<option value="ny">New York</option>
<option value="va">Virginia</option>
</select>
</div>
<div class="col-5">
<select class="custom-select browser-default mailing" name="m_state" id="m_state" required>
<option value="">--Select State--</option>
<option value="az">Arizona</option>
<option value="ia">Iowa</option>
<option value="mo">Missouri</option>
<option value="ny">New York</option>
<option value="va">Virginia</option>
</select>
</div>
</div>
<div class="form-group row required">
<label for="zip" class="col-2 col-form-label">Zip:</label>
<div class="col-5">
<input class="form-control physical" type="text" name="p_zip" id="p_zip" value="" pattern="(\d{5}([\-]\d{4})?)" data-dispfld="The required format is: xxxxx or xxxxx-xxxx" placeholder="Enter Zip Code, formatted: 99999 or 99999-9999" maxlength="10" required>
</div>
<div class="col-5">
<input class="form-control mailing" type="text" name="m_zip" id="m_zip" value="" pattern="(\d{5}([\-]\d{4})?)" data-dispfld="The required format is: xxxxx or xxxxx-xxxx" placeholder="Enter Zip Code, formatted: 99999 or 99999-9999" maxlength="10" required>
</div>
</div>
<div class="row">
<div class="col-12 text-center">
<button class="btn btn-outline-secondary" type="button" name="save" id="save">Save</button>
<button class="btn btn-outline-secondary" type="button" name="cancel" id="cancel">Cancel</button>
</div>
</div>
</form>
</div>
</div>
</div>
我的表格很长,在某些情况下用户可能会漏掉一些必填字段。如果他们一直滚动到 Save
按钮并单击以发送表单数据,他们将不会看到错误消息。我想知道是否有一种方法可以触发 on focus
方法,将用户带到表单中的第一个字段,即 required
或 invalid
。这是我的表格示例:
var COMMON_FUNC = {};
$("#save").on("click", function() {
var frmObject = $(this).closest("form"),
frmDisabledFlds = frmObject.find(":input:disabled").prop("disabled", false),
frmData = frmObject.serialize();
frmDisabledFlds.prop("disabled", true);
if (COMMON_FUNC.verifyFields("new-record")) {
console.log('Send Form Data!');
}
});
COMMON_FUNC.verifyFields = function(containerID, includeInvisible) {
includeInvisible = includeInvisible || false;
let isValid = true;
const hdlMap = {
'valueMissing': "This field is required",
'patternMismatch': "This field is invalid",
'tooLong': "This field is too long",
'rangeOverflow': "This field is greater than allowed maximum",
'rangeUnderflow': "This field is less than allowed minimum",
'typeMismatch': "This field is mistyped"
};
const arrV = Object.keys(hdlMap);
$("#" + containerID).find("input,textarea,select").each(function() {
var curItem$ = $(this);
var errMsg = [];
var dispfld = curItem$.data("dispfld");
if (includeInvisible || curItem$.is(":visible")) {
if (curItem$[0].validity.valid) {
curItem$.removeClass("is-invalid");
return;
}
arrV.forEach(function(prop) {
if (curItem$[0].validity[prop]) {
if (prop === "patternMismatch" && dispfld) {
errMsg.push(dispfld);
} else {
errMsg.push(hdlMap[prop]);
}
}
});
if (errMsg.length) {
if (!curItem$.next().is(".invalid-feedback")) {
curItem$.after('<div class="invalid-feedback"></div>');
}
curItem$.addClass("is-invalid").next().text(errMsg.join(' and '));
isValid = false;
} else {
curItem$.removeClass("is-invalid");
}
}
});
return isValid;
};
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>
<div class="container">
<div class="card">
<div class="card-header">
<h4>New Record</h4>
</div>
<div class="card-body">
<form name="new-record" id="new-record" autocomplete="off">
<div class="form-group">
<label for="bldg_name">Building Name:</label>
<input class="form-control" type="text" name="bldg_name" id="bldg_name" value="" maxlength="500" placeholder="Enter the building name" required>
</div>
<div class="row">
<div class="col-12"><strong><u>Manager</u></strong></div>
</div>
<div class="form-row">
<div class="form-group col-6">
<label for="salutation">Salutation:</label>
<select class="custom-select browser-default" name="salutation" id="salutation">
<option value="">--Select Salutation--</option>
<option value="1">Mrs</option>
<option value="2">Ms</option>
<option value="3">Miss</option>
<option value="4">Mr</option>
</select>
</div>
<div class="form-group col-6">
<label for="title">Business Title:</label>
<select class="custom-select browser-default" name="title" id="title">
<option value="">--Select Title--</option>
<option value="1">Region Manager</option>
<option value="2">State Manager</option>
<option value="3">Building Manager</option>
</select>
</div>
</div>
<div class="form-row">
<div class="form-group col-6 required">
<label for="fname">First Name:</label>
<input class="form-control" type="text" name="fname" id="fname" value="" maxlength="20" placeholder="Enter First name" required>
</div>
<div class="form-group col-6 required">
<label for="lname">Last Name:</label>
<input class="form-control" type="text" name="lname" id="lname" value="" maxlength="30" placeholder="Enter Last name" required>
</div>
</div>
<div class="form-group required">
<label for="email">Email:</label>
<input class="form-control email" type="email" name="email" id="email" maxlength="50" placeholder="Enter Email address" required>
</div>
<div class="form-group row">
<div class="col-5 offset-2"><strong><u>Physical Address</u></strong></div>
<div class="col-5"><strong><u>Mailing Address</u></strong></div>
</div>
<div class="form-group row required">
<label for="address1" class="col-2 col-form-label">Address 1:</label>
<div class="col-5">
<input class="form-control physical" type="text" name="p_address1" id="p_address1" value="" placeholder="Enter Physical Address 1" maxlength="40" required>
</div>
<div class="col-5">
<input class="form-control mailing" type="text" name="m_address1" id="m_address1" value="" placeholder="Enter Mailing Address 1" maxlength="40" required>
</div>
</div>
<div class="form-group row">
<label for="address2" class="col-2 col-form-label">Address 2:</label>
<div class="col-5">
<input class="form-control physical" type="text" name="p_address2" id="p_address2" value="" placeholder="Enter Physical Address 2" maxlength="40">
</div>
<div class="col-5">
<input class="form-control mailing" type="text" name="m_address2" id="m_address2" value="" placeholder="Enter Mailing Address 2" maxlength="40">
</div>
</div>
<div class="form-group row">
<label for="address3" class="col-2 col-form-label">Address 3:</label>
<div class="col-5">
<input class="form-control physical" type="text" name="p_address3" id="p_address3" value="" placeholder="Enter Physical Address 3" maxlength="40">
</div>
<div class="col-5">
<input class="form-control mailing" type="text" name="m_address3" id="m_address3" value="" placeholder="Enter Mailing Address 3" maxlength="40">
</div>
</div>
<div class="form-group row">
<label for="address4" class="col-2 col-form-label">Address 4:</label>
<div class="col-5">
<input class="form-control physical" type="text" name="p_address4" id="p_address4" value="" placeholder="Enter Physical Address 4" maxlength="40">
</div>
<div class="col-5">
<input class="form-control mailing" type="text" name="m_address4" id="m_address4" value="" placeholder="Enter Mailing Address 4" maxlength="40">
</div>
</div>
<div class="form-group row required">
<label for="city" class="col-2 col-form-label">City:</label>
<div class="col-5">
<input class="form-control physical" type="text" name="p_city" id="p_city" value="" placeholder="Enter City" maxlength="25" required>
</div>
<div class="col-5">
<input class="form-control mailing" type="text" name="m_city" id="m_city" value="" placeholder="Enter City" maxlength="25" required>
</div>
</div>
<div class="form-group row required">
<label for="state" class="col-2 col-form-label">State:</label>
<div class="col-5">
<select class="custom-select browser-default physical" name="p_state" id="p_state" required>
<option value="">--Select State--</option>
<option value="az">Arizona</option>
<option value="ia">Iowa</option>
<option value="mo">Missouri</option>
<option value="ny">New York</option>
<option value="va">Virginia</option>
</select>
</div>
<div class="col-5">
<select class="custom-select browser-default mailing" name="m_state" id="m_state" required>
<option value="">--Select State--</option>
<option value="az">Arizona</option>
<option value="ia">Iowa</option>
<option value="mo">Missouri</option>
<option value="ny">New York</option>
<option value="va">Virginia</option>
</select>
</div>
</div>
<div class="form-group row required">
<label for="zip" class="col-2 col-form-label">Zip:</label>
<div class="col-5">
<input class="form-control physical" type="text" name="p_zip" id="p_zip" value="" pattern="(\d{5}([\-]\d{4})?)" data-dispfld="The required format is: xxxxx or xxxxx-xxxx" placeholder="Enter Zip Code, formatted: 99999 or 99999-9999" maxlength="10" required>
</div>
<div class="col-5">
<input class="form-control mailing" type="text" name="m_zip" id="m_zip" value="" pattern="(\d{5}([\-]\d{4})?)" data-dispfld="The required format is: xxxxx or xxxxx-xxxx" placeholder="Enter Zip Code, formatted: 99999 or 99999-9999" maxlength="10" required>
</div>
</div>
<div class="row">
<div class="col-12 text-center">
<button class="btn btn-outline-secondary" type="button" name="save" id="save">Save</button>
<button class="btn btn-outline-secondary" type="button" name="cancel" id="cancel">Cancel</button>
</div>
</div>
</form>
</div>
</div>
</div>
您可以 运行 此示例并在表单中输入除建筑物名称之外的所有信息。然后您可以单击“保存”按钮,您将无法在顶部看到错误消息。如果有人对如何处理此问题有建议,请告诉我。我愿意听到针对这种情况的不同解决方案。
您可以尝试像这样简单的操作(未经测试但应该有效):
document.getElementsByClassName('is-invalid')[0].scrollIntoView({ behavior: 'smooth' });
这会查找错误 class is-invalid
然后平滑滚动到找到的第一个
验证后添加此代码,如果发现错误。
DOM API 对元素具有 "focus" 功能,可以满足您的需求。
将所有有效元素推送到 invalidInputs 数组,然后您可以选择第一个无效元素并对该元素调用 .focus()。
var COMMON_FUNC = {};
$("#save").on("click", function() {
var frmObject = $(this).closest("form"),
frmDisabledFlds = frmObject.find(":input:disabled").prop("disabled", false),
frmData = frmObject.serialize();
frmDisabledFlds.prop("disabled", true);
if (COMMON_FUNC.verifyFields("new-record")) {
console.log('Send Form Data!');
}
});
COMMON_FUNC.verifyFields = function(containerID, includeInvisible) {
includeInvisible = includeInvisible || false;
let isValid = true;
const hdlMap = {
'valueMissing': "This field is required",
'patternMismatch': "This field is invalid",
'tooLong': "This field is too long",
'rangeOverflow': "This field is greater than allowed maximum",
'rangeUnderflow': "This field is less than allowed minimum",
'typeMismatch': "This field is mistyped"
};
const arrV = Object.keys(hdlMap);
// Create an array for the invalid fields.
const invalidInputs = [];
$("#" + containerID).find("input,textarea,select").each(function() {
var curItem$ = $(this);
var errMsg = [];
var dispfld = curItem$.data("dispfld");
if (includeInvisible || curItem$.is(":visible")) {
if (curItem$[0].validity.valid) {
curItem$.removeClass("is-invalid");
return;
}
arrV.forEach(function(prop) {
if (curItem$[0].validity[prop]) {
if (prop === "patternMismatch" && dispfld) {
errMsg.push(dispfld);
} else {
errMsg.push(hdlMap[prop]);
}
}
});
if (errMsg.length) {
if (!curItem$.next().is(".invalid-feedback")) {
curItem$.after('<div class="invalid-feedback"></div>');
}
curItem$.addClass("is-invalid").next().text(errMsg.join(' and '));
isValid = false;
//Push the invalid inputs onto the invalidInputs array.
invalidInputs.push(curItem$);
} else {
curItem$.removeClass("is-invalid");
}
}
});
// Focus on the first element that is invalid.
invalidInputs[0].focus();
return isValid;
};
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>
<div class="container">
<div class="card">
<div class="card-header">
<h4>New Record</h4>
</div>
<div class="card-body">
<form name="new-record" id="new-record" autocomplete="off">
<div class="form-group">
<label for="bldg_name">Building Name:</label>
<input class="form-control" type="text" name="bldg_name" id="bldg_name" value="" maxlength="500" placeholder="Enter the building name" required>
</div>
<div class="row">
<div class="col-12"><strong><u>Manager</u></strong></div>
</div>
<div class="form-row">
<div class="form-group col-6">
<label for="salutation">Salutation:</label>
<select class="custom-select browser-default" name="salutation" id="salutation">
<option value="">--Select Salutation--</option>
<option value="1">Mrs</option>
<option value="2">Ms</option>
<option value="3">Miss</option>
<option value="4">Mr</option>
</select>
</div>
<div class="form-group col-6">
<label for="title">Business Title:</label>
<select class="custom-select browser-default" name="title" id="title">
<option value="">--Select Title--</option>
<option value="1">Region Manager</option>
<option value="2">State Manager</option>
<option value="3">Building Manager</option>
</select>
</div>
</div>
<div class="form-row">
<div class="form-group col-6 required">
<label for="fname">First Name:</label>
<input class="form-control" type="text" name="fname" id="fname" value="" maxlength="20" placeholder="Enter First name" required>
</div>
<div class="form-group col-6 required">
<label for="lname">Last Name:</label>
<input class="form-control" type="text" name="lname" id="lname" value="" maxlength="30" placeholder="Enter Last name" required>
</div>
</div>
<div class="form-group required">
<label for="email">Email:</label>
<input class="form-control email" type="email" name="email" id="email" maxlength="50" placeholder="Enter Email address" required>
</div>
<div class="form-group row">
<div class="col-5 offset-2"><strong><u>Physical Address</u></strong></div>
<div class="col-5"><strong><u>Mailing Address</u></strong></div>
</div>
<div class="form-group row required">
<label for="address1" class="col-2 col-form-label">Address 1:</label>
<div class="col-5">
<input class="form-control physical" type="text" name="p_address1" id="p_address1" value="" placeholder="Enter Physical Address 1" maxlength="40" required>
</div>
<div class="col-5">
<input class="form-control mailing" type="text" name="m_address1" id="m_address1" value="" placeholder="Enter Mailing Address 1" maxlength="40" required>
</div>
</div>
<div class="form-group row">
<label for="address2" class="col-2 col-form-label">Address 2:</label>
<div class="col-5">
<input class="form-control physical" type="text" name="p_address2" id="p_address2" value="" placeholder="Enter Physical Address 2" maxlength="40">
</div>
<div class="col-5">
<input class="form-control mailing" type="text" name="m_address2" id="m_address2" value="" placeholder="Enter Mailing Address 2" maxlength="40">
</div>
</div>
<div class="form-group row">
<label for="address3" class="col-2 col-form-label">Address 3:</label>
<div class="col-5">
<input class="form-control physical" type="text" name="p_address3" id="p_address3" value="" placeholder="Enter Physical Address 3" maxlength="40">
</div>
<div class="col-5">
<input class="form-control mailing" type="text" name="m_address3" id="m_address3" value="" placeholder="Enter Mailing Address 3" maxlength="40">
</div>
</div>
<div class="form-group row">
<label for="address4" class="col-2 col-form-label">Address 4:</label>
<div class="col-5">
<input class="form-control physical" type="text" name="p_address4" id="p_address4" value="" placeholder="Enter Physical Address 4" maxlength="40">
</div>
<div class="col-5">
<input class="form-control mailing" type="text" name="m_address4" id="m_address4" value="" placeholder="Enter Mailing Address 4" maxlength="40">
</div>
</div>
<div class="form-group row required">
<label for="city" class="col-2 col-form-label">City:</label>
<div class="col-5">
<input class="form-control physical" type="text" name="p_city" id="p_city" value="" placeholder="Enter City" maxlength="25" required>
</div>
<div class="col-5">
<input class="form-control mailing" type="text" name="m_city" id="m_city" value="" placeholder="Enter City" maxlength="25" required>
</div>
</div>
<div class="form-group row required">
<label for="state" class="col-2 col-form-label">State:</label>
<div class="col-5">
<select class="custom-select browser-default physical" name="p_state" id="p_state" required>
<option value="">--Select State--</option>
<option value="az">Arizona</option>
<option value="ia">Iowa</option>
<option value="mo">Missouri</option>
<option value="ny">New York</option>
<option value="va">Virginia</option>
</select>
</div>
<div class="col-5">
<select class="custom-select browser-default mailing" name="m_state" id="m_state" required>
<option value="">--Select State--</option>
<option value="az">Arizona</option>
<option value="ia">Iowa</option>
<option value="mo">Missouri</option>
<option value="ny">New York</option>
<option value="va">Virginia</option>
</select>
</div>
</div>
<div class="form-group row required">
<label for="zip" class="col-2 col-form-label">Zip:</label>
<div class="col-5">
<input class="form-control physical" type="text" name="p_zip" id="p_zip" value="" pattern="(\d{5}([\-]\d{4})?)" data-dispfld="The required format is: xxxxx or xxxxx-xxxx" placeholder="Enter Zip Code, formatted: 99999 or 99999-9999" maxlength="10" required>
</div>
<div class="col-5">
<input class="form-control mailing" type="text" name="m_zip" id="m_zip" value="" pattern="(\d{5}([\-]\d{4})?)" data-dispfld="The required format is: xxxxx or xxxxx-xxxx" placeholder="Enter Zip Code, formatted: 99999 or 99999-9999" maxlength="10" required>
</div>
</div>
<div class="row">
<div class="col-12 text-center">
<button class="btn btn-outline-secondary" type="button" name="save" id="save">Save</button>
<button class="btn btn-outline-secondary" type="button" name="cancel" id="cancel">Cancel</button>
</div>
</div>
</form>
</div>
</div>
</div>