Add validations to Input lib

This commit is contained in:
cyril lopez 2017-09-04 11:08:50 +02:00
parent 4330079b84
commit 1e17ea07e4
5 changed files with 95 additions and 8 deletions

View File

@ -5,7 +5,7 @@
*/ */
import React from 'react'; import React from 'react';
import { get, isEmpty, map, isObject } from 'lodash'; import { get, isEmpty, map, mapKeys, isObject, reject, includes } from 'lodash';
import { FormattedMessage } from 'react-intl'; import { FormattedMessage } from 'react-intl';
import styles from './styles.scss'; import styles from './styles.scss';
@ -34,6 +34,65 @@ class Input extends React.Component { // eslint-disable-line react/prefer-statel
} }
} }
handleBlur = ({ target }) => {
// prevent error display if input is initially empty
if (!isEmpty(target.value) || this.state.hasInitialValue) {
// validates basic string validations
// add custom logic here such as alerts...
const errors = this.validate(target.value);
this.setState({ errors, hasInitialValue: true });
}
}
validate = (value) => {
let errors = [];
// handle i18n
const requiredError = { id: 'error.validation.required' };
mapKeys(this.props.validations, (validationValue, validationKey) => {
switch (validationKey) {
case 'max':
if (parseInt(value, 10) > validationValue) {
errors.push({ id: 'error.validation.max' });
}
break;
case 'maxLength':
if (value.length > validationValue) {
errors.push({ id: 'error.validation.maxLength' });
}
break;
case 'min':
if (parseInt(value, 10) < validationValue) {
errors.push({ id: 'error.validation.min' });
}
break;
case 'minLength':
if (value.length < validationValue) {
errors.push({ id: 'error.validation.minLength' });
}
break;
case 'required':
if (value.length === 0) {
errors.push({ id: 'error.validation.required' });
}
break;
case 'regex':
if (!new RegExp(validationValue).test(value)) {
errors.push({ id: 'error.validation.regex' });
}
break;
default:
errors = [];
}
});
if (includes(errors, requiredError)) {
errors = reject(errors, (error) => error !== requiredError);
}
return errors;
}
handleChangeCheckbox = (e) => { handleChangeCheckbox = (e) => {
const target = { const target = {
type: e.target.type, type: e.target.type,
@ -239,7 +298,10 @@ Input.propTypes = {
customBootstrapClass: React.PropTypes.string, customBootstrapClass: React.PropTypes.string,
deactivateErrorHighlight: React.PropTypes.bool, deactivateErrorHighlight: React.PropTypes.bool,
// errors: React.PropTypes.array, // errors: React.PropTypes.array,
handleBlur: React.PropTypes.func, handleBlur: React.PropTypes.oneOfType([
React.PropTypes.func,
React.PropTypes.bool,
]),
handleChange: React.PropTypes.func.isRequired, handleChange: React.PropTypes.func.isRequired,
handleFocus: React.PropTypes.func, handleFocus: React.PropTypes.func,
inputDescription: React.PropTypes.string, inputDescription: React.PropTypes.string,

View File

@ -19,8 +19,12 @@ class PopUpForm extends React.Component { // eslint-disable-line react/prefer-st
'col-md-8 offset-md-4 pull-md-4' : 'col-md-6 offset-md-6 pull-md-6'; 'col-md-8 offset-md-4 pull-md-4' : 'col-md-6 offset-md-6 pull-md-6';
const shouldOverrideRendering = this.props.overrideRenderInputCondition ? this.props.overrideRenderInputCondition(item) : false; const shouldOverrideRendering = this.props.overrideRenderInputCondition ? this.props.overrideRenderInputCondition(item) : false;
const shouldOverrideHandleBlur = this.props.overrideHandleBlurCondition ? this.props.overrideHandleBlurCondition(item) : false;
const value = !isEmpty(this.props.values) && includes(item.target, '.') ? get(this.props.values, [split(item.target, '.')[0], split(item.target, '.')[1]]) : this.props.values[item.target]; const value = !isEmpty(this.props.values) && includes(item.target, '.') ? get(this.props.values, [split(item.target, '.')[0], split(item.target, '.')[1]]) : this.props.values[item.target];
const handleBlur = shouldOverrideHandleBlur ? this.props.handleBlur : false;
if (shouldOverrideRendering) { if (shouldOverrideRendering) {
return this.props.overrideRenderInput(item, key); return this.props.overrideRenderInput(item, key);
} }
@ -30,7 +34,7 @@ class PopUpForm extends React.Component { // eslint-disable-line react/prefer-st
key={key} key={key}
type={item.type} type={item.type}
handleChange={this.props.handleChange} handleChange={this.props.handleChange}
handleBlur={this.props.handleBlur} handleBlur={handleBlur}
name={item.name} name={item.name}
target={item.target} target={item.target}
validations={item.validations} validations={item.validations}
@ -116,6 +120,7 @@ PopUpForm.propTypes = {
isOpen: React.PropTypes.bool, isOpen: React.PropTypes.bool,
noButtons: React.PropTypes.bool, noButtons: React.PropTypes.bool,
noNav: React.PropTypes.bool, noNav: React.PropTypes.bool,
overrideHandleBlurCondition: React.PropTypes.func,
overrideRenderInput: React.PropTypes.func, overrideRenderInput: React.PropTypes.func,
overrideRenderInputCondition: React.PropTypes.func, overrideRenderInputCondition: React.PropTypes.func,
// popUpFormType: React.PropTypes.string.isRequired, // popUpFormType: React.PropTypes.string.isRequired,

View File

@ -233,6 +233,16 @@ export class Form extends React.Component { // eslint-disable-line react/prefer-
router.push(`${this.props.routePath}#create${this.props.modelName}::attribute${attributeType}::baseSettings`); router.push(`${this.props.routePath}#create${this.props.modelName}::attribute${attributeType}::baseSettings`);
} }
checkForNestedInput = (item) => {
const hasNestedInput = item.items && item.type !== 'select';
return hasNestedInput;
}
checkInputContentType = (item) => {
const shouldOverrideHandleBlur = item.target === 'name' && includes(this.props.hash, 'contentType');
return shouldOverrideHandleBlur;
}
handleBlur = ({ target }) => { handleBlur = ({ target }) => {
if (target.name === 'name') { if (target.name === 'name') {
this.props.changeInput(target.name, camelCase(target.value), includes(this.props.hash, 'edit')); this.props.changeInput(target.name, camelCase(target.value), includes(this.props.hash, 'edit'));
@ -336,11 +346,6 @@ export class Form extends React.Component { // eslint-disable-line react/prefer-
} }
} }
checkForNestedInput = (item) => {
const hasNestedInput = item.items && item.type !== 'select';
return hasNestedInput;
}
renderInput = (item, key) => ( renderInput = (item, key) => (
<InputCheckboxWithNestedInputs <InputCheckboxWithNestedInputs
key={key} key={key}
@ -404,6 +409,7 @@ export class Form extends React.Component { // eslint-disable-line react/prefer-
buttonSubmitMessage={buttonSubmitMessage} buttonSubmitMessage={buttonSubmitMessage}
showLoader={this.props.showButtonLoading} showLoader={this.props.showButtonLoading}
renderCustomPopUpHeader={renderCustomPopUpHeader} renderCustomPopUpHeader={renderCustomPopUpHeader}
overrideHandleBlurCondition={this.checkInputContentType}
/> />
</div> </div>
); );

View File

@ -13,6 +13,13 @@
"button.contentType.add": "Add Content Type", "button.contentType.add": "Add Content Type",
"button.attributes.add": "Add New Field", "button.attributes.add": "Add New Field",
"error.validation.required": "This value input is required.",
"error.validation.regex": "The value not match the regex.",
"error.validation.max": "The value is too high.",
"error.validation.min": "The value is too low.",
"error.validation.maxLength": "The value is too long.",
"error.validation.minLength": "The value is too shot.",
"form.attribute.item.textarea.name": "Name", "form.attribute.item.textarea.name": "Name",
"form.attribute.item.date.name": "Name", "form.attribute.item.date.name": "Name",
"form.attribute.item.media.name": "Name", "form.attribute.item.media.name": "Name",

View File

@ -12,6 +12,13 @@
"button.contentType.add": "Ajouter un modèle", "button.contentType.add": "Ajouter un modèle",
"button.attributes.add": "Ajouter un champs", "button.attributes.add": "Ajouter un champs",
"error.validation.required": "Ce champ est obligatoire.",
"error.validation.regex": "La valeur ne correspond pas au format attendu.",
"error.validation.max": "La valeur est trop grande.",
"error.validation.min": "La valeur est trop basse.",
"error.validation.maxLength": "La valeur est trop longue.",
"error.validation.minLength": "La valeur est trop courte.",
"form.attribute.item.textarea.name": "Nom", "form.attribute.item.textarea.name": "Nom",
"form.attribute.item.date.name": "Nom", "form.attribute.item.date.name": "Nom",
"form.attribute.item.boolean.name": "Nom", "form.attribute.item.boolean.name": "Nom",