Integrating server-side verification into client-side forms often requires careful alignment between frontend validation plugins and backend endpoints. When utilizing BootstrapValidator's asynchronous remote rule, developers frequently encounter integration hurdles due to limited default documentation. Successful implementation depends on strictly adhering to the expected server response payload and configuring the AJAX trigger parameters correctly.
Required Server Resposne Structure
The validation engine exclusiveyl parses a boolean flag wrapped in a JSON object. Deviations from this schema—including nested wrappers, string representations of booleans, or mismatched key casing—will cause the plugin to fail silent or leave fields in an unverified state. The endpoint must return either:
{"valid": true}
for accepted values, or:
{"valid": false}
for rejected entries. The HTTP status code should ideally remain 200 OK to prevent the AJAX failure callback from interrupting the validation cycle.
Backend Endpoint Implementation
Modern frameworks simplify the payload construction. Below is a refactored Spring Boot controller example that replaces manual collection iteration with a repository lookup, renames identifiers for clarity, and guarantees the exact JSON structure required by the validator.
@RestController
@RequestMapping("/api/forms")
public class FormVerificationController {
private final MembershipRepository membershipRepo;
public FormVerificationController(MembershipRepository repo) {
this.membershipRepo = repo;
}
@PostMapping("/checkHandleAvailability")
public ResponseEntity<Map<String, Boolean>> verifyHandle(@RequestParam String handle) {
boolean isAvailable = !membershipRepo.doesHandleExist(handle.trim().toLowerCase());
Map<String, Boolean> validationResponse = Map.of("valid", isAvailable);
return ResponseEntity.ok(validationResponse);
}
}
Frontend Configuration & Submission Workflow
The client-side setup groups synchronous rules alongside asynchronous checks. Key properties like threshold and delay control request frequency, preventing excessive server load during rapid keystrokes. The configuration below demonstrates optimized syntax, renamed selectors, and a secure form submission listener.
<script>
$(document).ready(function() {
const $accountForm = $('#createAccountForm');
$accountForm.bootstrapValidator({
message: 'Input does not meet system requirements',
feedbackIcons: {
valid: 'glyphicon glyphicon-ok',
invalid: 'glyphicon glyphicon-remove',
validating: 'glyphicon glyphicon-refresh'
},
fields: {
loginHandle: {
validators: {
notEmpty: { message: 'Display name is required' },
stringLength: { min: 3, max: 24, message: 'Length must be between 3 and 24 characters' },
threshold: 3,
delay: 1500,
remote: {
url: '/api/forms/checkHandleAvailability',
type: 'POST',
message: 'This display name is already registered',
data: function(validator) {
return {
handle: $('[name="loginHandle"]').val(),
region: $('[name="userRegion"]').val()
};
},
json: true
}
}
},
secretKey: {
validators: {
notEmpty: { message: 'Access credential cannot be blank' },
stringLength: { min: 8, max: 64, message: 'Credential length must be between 8 and 64 characters' },
regexp: {
regexp: /^[A-Za-z0-9!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?]+$/,
message: 'Only alphanumeric and standard punctuation allowed'
}
}
},
repeatKey: {
validators: {
identical: {
field: 'secretKey',
message: 'Confirmation does not match initial entry'
}
}
},
contactAddress: {
validators: {
notEmpty: { message: 'Routing information is mandatory' },
emailAddress: { message: 'Provide a valid SMTP-compatible address' }
}
}
}
})
.on('success.form.bv', function(e) {
e.preventDefault();
const submittedData = $accountForm.serialize();
const endpointUrl = $accountForm.attr('action');
$.ajax({
url: endpointUrl,
type: 'POST',
data: submittedData,
dataType: 'json',
success: function(response) {
console.log('Process completed successfully:', response);
window.location.href = '/dashboard';
},
error: function(xhr, status, error) {
console.error('Submission failure:', error);
}
});
});
});
</script>