-
Notifications
You must be signed in to change notification settings - Fork 39
Validation
Mev-Rael edited this page Feb 26, 2016
·
1 revision
Form can be divided to many steps (tabs).
Recommended way styling form tabs is Bootstrap 4 nav tabs and there is BunnyJS TabList
component to work with tab contents, tab panels and associated nav and links.
.tab-content must have an ID attribute.
If user can change step to any tab listen to on_focus
event, check if invalid input is in another tab and swith tab manually. Example:
Validate.validate(document.getElementById('add_edit_user_form'), {
on_focus: function(form_input, form_group) {
// if form input is inside tab pane, check and switch to required tab pane
var parent = form_group.parentNode;
if (parent.classList.contains('tab-pane')) {
if (!parent.classList.contains('active')) {
TabList.changeTab(parent.getAttribute('id'));
}
}
// focus and scroll to visible part of invalid input
// if we are using .fade class to animate tab switching wrap into setTimeout()
setTimeout(function() {
Validate.focus(form_input);
}, 200);
}
});
Sometimes only parts of form should be validated not all form. For example:
- when only one row should be checked,
- or only one step
- or if user can't change tabs at any time
- or there are no associated
<nav>
with tab links to switch tab form UI for .tab-content.
In that case form should be manually validated step by step using Validate.validateSection()
. In the example below there is also a custom ajax valdiation:
<form id="steps_form" ...>
<div id="steps_tab_content" class="tab-content"> <!-- adding ID to tab-content -->
<div class="tab-pane active" id="step1" role="tabpanel"> <!-- first section with id="step1" and also .active -->
<form group and input ...>
<!-- each input must be within form group element which contains only one input, only one label and can contain only
one container for error message. We are using default Bootstrap 4 markup here -->
<div id="email_group" class="form-group"> <!-- id added to this form group because we will add custom ajax validator for this input -->
<input type="email" name="email"> <!-- below is example how to valdiate email via ajax and check if email is already registered -->
</div>
<button id="btn_step1" type="button" class="btn btn-primary">Go to step 2</button> <!-- Creating button at the end of each section and later will add event listener on click -->
</div>
<div class="tab-pane" id="step2" role="tabpanel"> <!-- next section with id="step2" and without .active (hidden) -->
<input ...>
<input ...>
<button id="btn_step2" type="button" class="btn btn-primary">Continue</button> <!-- step 2 button -->
</div>
<div class="tab-pane" id="step3" role="tabpanel"> <!-- last section with id="step3" -->
<input ...>
<input ...>
<button id="btn_finish" type="button" class="btn btn-primary">Finish</button> <!-- and last button -->
</div>
</div>
</form>
And now custom JS to validate form by sections:
// when user clicks on "Go to step 2" button at the end of first section
document.getElementById('btn_step1').addEventListener('click', function() {
// validateSection() returns true when section is valid
if (Validate.validateSection(document.getElementById('step1'))) {
// when first section is valid AJAX request is made to check if email exists
// first need to get form group element and input element.
// getInputElementsByFormGroup(form_group_id_or_el) will return an object with keys: formGroup, input and label
// to make custom validator we need formGroup and input
var email_input_elements = Validate.getInputElementsByFormGroup('email_group');
// making an AJAX request to check if e-mail already registered
Ajax.get('/api/v1/users/check-email/' + encodeURI(email_input_elements.input.value), function(data) {
var $data = JSON.parse(data);
if ($data.status !== 'success') {
// email already exists, create error message
// setErrorMessage(form_group_el, msg)
Validate.setErrorMessage(email_input_elements.formGroup, 'E-mail "' + email_input_elements.input.value + '" is already registered!');
// changing focus and scrolling to invalid input
Validate.focus(email_input_elements.input);
} else {
// email is not registered and our last custom validator is passed, change to next tab.
TabList.changeTab('step2');
}
});
}
});
// second button will be shown only after first section passed because it is inside hidden section by default
// and becomes visible whentab is changed
// Adding event listener when user clicks on second step button
document.getElementById('btn_step2').addEventListener('click', function() {
// when we don't have cusotm ajax validators it's very easy
if (Validate.validateSection(document.getElementById('step2'))) {
// if section 2 is valid, go to next section
TabList.changeTab('step3');
}
});
// and the last section event listener, since we don't have a submit button in form
// we need to manually submit form when last section is valid.
document.getElementById('btn_finish').addEventListener('click', function() {
if (Validate.validateSection(document.getElementById('step3'))) {
document.getElementById('steps_form').submit();
}
});