Fix errors, get validation running for signup box and sign in.
This commit is contained in:
parent
a449b9b8a1
commit
00bfb645e1
3 changed files with 38 additions and 28 deletions
|
@ -17,10 +17,10 @@
|
||||||
const inputErrorClass = 'gl-field-error-outline';
|
const inputErrorClass = 'gl-field-error-outline';
|
||||||
|
|
||||||
class GlFieldError {
|
class GlFieldError {
|
||||||
constructor({ input, form }) {
|
constructor({ input, formErrors }) {
|
||||||
this.inputElement = $(input);
|
this.inputElement = $(input);
|
||||||
this.inputDomElement = this.inputElement.get(0);
|
this.inputDomElement = this.inputElement.get(0);
|
||||||
this.form = form;
|
this.form = formErrors;
|
||||||
this.errorMessage = this.inputElement.attr('title') || 'This field is required.';
|
this.errorMessage = this.inputElement.attr('title') || 'This field is required.';
|
||||||
this.fieldErrorElement = $(`<p class='${errorMessageClass} hide'>${ this.errorMessage }</p>`);
|
this.fieldErrorElement = $(`<p class='${errorMessageClass} hide'>${ this.errorMessage }</p>`);
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@
|
||||||
|
|
||||||
initFieldValidation() {
|
initFieldValidation() {
|
||||||
// hidden when injected into DOM
|
// hidden when injected into DOM
|
||||||
$input.after(this.fieldErrorElement);
|
this.inputElement.after(this.fieldErrorElement);
|
||||||
this.inputElement.off('invalid').on('invalid', this.handleInvalidInput.bind(this));
|
this.inputElement.off('invalid').on('invalid', this.handleInvalidInput.bind(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,24 +42,24 @@
|
||||||
this.setClearState();
|
this.setClearState();
|
||||||
|
|
||||||
if (this.state.valid) {
|
if (this.state.valid) {
|
||||||
this.setValidState();
|
return this.setValidState();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.state.empty) {
|
if (this.state.empty) {
|
||||||
this.setEmptyState();
|
return this.setEmptyState();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.state.valid) {
|
if (!this.state.valid) {
|
||||||
this.setInvalidState();
|
return this.setInvalidState();
|
||||||
}
|
}
|
||||||
|
|
||||||
this.form.focusOnFirstInvalid.apply(this);
|
this.form.focusOnFirstInvalid.apply(this.form);
|
||||||
}
|
}
|
||||||
|
|
||||||
handleInvalidInput(event) {
|
handleInvalidInput(event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
||||||
this.state.valid = true;
|
this.state.valid = false;
|
||||||
this.state.empty = false;
|
this.state.empty = false;
|
||||||
|
|
||||||
this.renderValidity();
|
this.renderValidity();
|
||||||
|
@ -77,8 +77,7 @@
|
||||||
updateValidityState() {
|
updateValidityState() {
|
||||||
const inputVal = this.inputElement.val();
|
const inputVal = this.inputElement.val();
|
||||||
this.state.empty = !!inputVal.length;
|
this.state.empty = !!inputVal.length;
|
||||||
this.state.valid = this.getInputValidity;
|
this.state.valid = this.getInputValidity();
|
||||||
|
|
||||||
this.renderValidity();
|
this.renderValidity();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,17 +86,24 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
setEmptyState() {
|
setEmptyState() {
|
||||||
return this.setClearState();
|
return this.setInvalidState();
|
||||||
}
|
}
|
||||||
|
|
||||||
setInvalidState() {
|
setInvalidState() {
|
||||||
$input.addClass(inputErrorClass);
|
this.inputElement.addClass(inputErrorClass);
|
||||||
return this.$fieldErrorElement.show();
|
this.inputElement.siblings('p').hide();
|
||||||
|
return this.fieldErrorElement.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
setClearState() {
|
setClearState() {
|
||||||
$input.removeClass(inputErrorClass);
|
const inputVal = this.inputElement.val();
|
||||||
return this.fieldErrorElement.hide();
|
if (!inputVal.split(' ').length) {
|
||||||
|
const trimmedInput = this.inputElement.val().trim();
|
||||||
|
this.inputElement.val(trimmedInput);
|
||||||
|
}
|
||||||
|
this.inputElement.removeClass(inputErrorClass);
|
||||||
|
this.inputElement.siblings('p').hide();
|
||||||
|
this.fieldErrorElement.hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
checkFieldValidity(target) {
|
checkFieldValidity(target) {
|
||||||
|
@ -105,19 +111,23 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const customValidationFlag = 'no-gl-field-errors';
|
||||||
|
|
||||||
class GlFieldErrors {
|
class GlFieldErrors {
|
||||||
constructor(form) {
|
constructor(form) {
|
||||||
this.form = $(form);
|
this.form = $(form);
|
||||||
|
this.state = {
|
||||||
|
inputs: [],
|
||||||
|
valid: false
|
||||||
|
};
|
||||||
this.initValidators();
|
this.initValidators();
|
||||||
}
|
}
|
||||||
|
|
||||||
initValidators () {
|
initValidators () {
|
||||||
// select all non-hidden inputs in form
|
// select all non-hidden inputs in form
|
||||||
const form = this.form;
|
this.state.inputs = this.form.find(':input:not([type=hidden])').toArray()
|
||||||
|
.filter((input) => !input.classList.contains(customValidationFlag))
|
||||||
this.inputs = this.form.find(':input:not([type=hidden])')
|
.map((input) => new GlFieldError({ input, formErrors: this }));
|
||||||
.toArray()
|
|
||||||
.map((input) => new GlFieldError({ input, form }));
|
|
||||||
|
|
||||||
this.form.on('submit', this.catchInvalidFormSubmit);
|
this.form.on('submit', this.catchInvalidFormSubmit);
|
||||||
}
|
}
|
||||||
|
@ -134,7 +144,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
focusOnFirstInvalid () {
|
focusOnFirstInvalid () {
|
||||||
const firstInvalid = this.inputs.find((input) => !input.validity.valid);
|
const firstInvalid = this.state.inputs.find((input) => !input.inputDomElement.validity.valid);
|
||||||
$(firstInvalid).focus();
|
$(firstInvalid).focus();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
const debounceTimeout = _.debounce((username) => {
|
const debounceTimeout = _.debounce((username) => {
|
||||||
this.state.validateUsername(username);
|
this.validateUsername(username);
|
||||||
}, debounceTimeoutDuration);
|
}, debounceTimeoutDuration);
|
||||||
|
|
||||||
this.inputElement.on('keyup.username_check', () => {
|
this.inputElement.on('keyup.username_check', () => {
|
||||||
|
@ -78,7 +78,7 @@
|
||||||
type: 'GET',
|
type: 'GET',
|
||||||
url: `/u/${username}/exists`,
|
url: `/u/${username}/exists`,
|
||||||
dataType: 'json',
|
dataType: 'json',
|
||||||
success: (res) => this.updateValidationState(res.exists)
|
success: (res) => this.setAvailabilityState(res.exists)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -96,10 +96,10 @@
|
||||||
|
|
||||||
clearFieldValidationState() {
|
clearFieldValidationState() {
|
||||||
// TODO: Double check if this is valid chaining
|
// TODO: Double check if this is valid chaining
|
||||||
const $input = this.inputElement
|
this.inputElement.siblings('p').hide();
|
||||||
.siblings('p').hide().end()
|
|
||||||
.removeClass(invalidInputClass);
|
this.inputElement.removeClass(invalidInputClass)
|
||||||
removeClass(successInputClass);
|
.removeClass(successInputClass);
|
||||||
}
|
}
|
||||||
|
|
||||||
setUnavailableState() {
|
setUnavailableState() {
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
= f.text_field :name, class: "form-control top", required: true, title: "This field is required."
|
= f.text_field :name, class: "form-control top", required: true, title: "This field is required."
|
||||||
%div.username.form-group
|
%div.username.form-group
|
||||||
= f.label :username
|
= f.label :username
|
||||||
= f.text_field :username, class: "form-control middle", pattern: "[a-zA-Z0-9]+", required: true
|
= f.text_field :username, class: "form-control middle no-gl-field-error", pattern: "[a-zA-Z0-9]+", required: true
|
||||||
%p.gl-field-error.hide Please create a username with only alphanumeric characters.
|
%p.gl-field-error.hide Please create a username with only alphanumeric characters.
|
||||||
%p.validation-error.hide Username is already taken.
|
%p.validation-error.hide Username is already taken.
|
||||||
%p.validation-success.hide Username is available.
|
%p.validation-success.hide Username is available.
|
||||||
|
|
Loading…
Reference in a new issue