I have form that is long and in some situations users might miss some of the required fields. If they scroll all the way to the Save
button and click to send the form data they won't see error message. I'm wondering if there is a way to trigger on focus
method that will take user to the first field in the form that is required
or invalid
. Here is example of my form:
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>
You can run this example and enter all information in the form but Building Name. Then you can click Save button, and you won;t be able to see the error message on the top. If anyone have suggestions how to handle this problem please let me know. I open to hear different solutions for this situations.