UNPKG

availity-reactstrap-validation

Version:
798 lines (622 loc) 26.3 kB
'use strict'; exports.__esModule = true; var _promise = require('babel-runtime/core-js/promise'); var _promise2 = _interopRequireDefault(_promise); var _extends2 = require('babel-runtime/helpers/extends'); var _extends3 = _interopRequireDefault(_extends2); var _objectWithoutProperties2 = require('babel-runtime/helpers/objectWithoutProperties'); var _objectWithoutProperties3 = _interopRequireDefault(_objectWithoutProperties2); var _regenerator = require('babel-runtime/regenerator'); var _regenerator2 = _interopRequireDefault(_regenerator); var _keys = require('babel-runtime/core-js/object/keys'); var _keys2 = _interopRequireDefault(_keys); var _asyncToGenerator2 = require('babel-runtime/helpers/asyncToGenerator'); var _asyncToGenerator3 = _interopRequireDefault(_asyncToGenerator2); var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck'); var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn'); var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); var _inherits2 = require('babel-runtime/helpers/inherits'); var _inherits3 = _interopRequireDefault(_inherits2); var _typeof2 = require('babel-runtime/helpers/typeof'); var _typeof3 = _interopRequireDefault(_typeof2); var _react = require('react'); var _react2 = _interopRequireDefault(_react); var _propTypes = require('prop-types'); var _propTypes2 = _interopRequireDefault(_propTypes); var _AvInputContainer = require('./AvInputContainer'); var _AvInputContainer2 = _interopRequireDefault(_AvInputContainer); var _AvValidator = require('./AvValidator'); var _AvValidator2 = _interopRequireDefault(_AvValidator); var _reactstrap = require('reactstrap'); var _classnames = require('classnames'); var _classnames2 = _interopRequireDefault(_classnames); var _get2 = require('lodash/get'); var _get3 = _interopRequireDefault(_get2); var _set2 = require('lodash/set'); var _set3 = _interopRequireDefault(_set2); var _throttle2 = require('lodash/throttle'); var _throttle3 = _interopRequireDefault(_throttle2); var _isString = require('lodash/isString'); var _isString2 = _interopRequireDefault(_isString); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } var getInputErrorMessage = function getInputErrorMessage(input, ruleName) { var errorMessage = input && input.props && input.props.errorMessage; if ((typeof errorMessage === 'undefined' ? 'undefined' : (0, _typeof3.default)(errorMessage)) === 'object') { return errorMessage[ruleName]; } return errorMessage; }; var AvForm = function (_InputContainer) { (0, _inherits3.default)(AvForm, _InputContainer); function AvForm() { var _this2 = this; var _temp, _this, _ret; (0, _classCallCheck3.default)(this, AvForm); for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } return _ret = (_temp = (_this = (0, _possibleConstructorReturn3.default)(this, _InputContainer.call.apply(_InputContainer, [this].concat(args))), _this), _this._isMounted = false, _this.state = { invalidInputs: {}, dirtyInputs: {}, touchedInputs: {}, badInputs: {}, submitted: false }, _this.validations = {}, _this.handleSubmit = function () { var _ref = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee(e) { var values, _ref2, isValid, errors; return _regenerator2.default.wrap(function _callee$(_context) { while (1) { switch (_context.prev = _context.next) { case 0: if (_this.props.beforeSubmitValidation) { _this.props.beforeSubmitValidation(e); } if (e && typeof e.preventDefault === 'function') { e.preventDefault(); } if (!_this.props.disabled) { _context.next = 4; break; } return _context.abrupt('return'); case 4: values = _this.getValues(); _context.next = 7; return _this.validateAll(values, false); case 7: _ref2 = _context.sent; isValid = _ref2.isValid; errors = _ref2.errors; _this.setTouched((0, _keys2.default)(_this._inputs), true, false); _this.updateInputs(); _this.props.onSubmit(e, errors, values); if (isValid) { _this.props.onValidSubmit(e, values); } else { _this.props.onInvalidSubmit(e, errors, values); } !_this.state.submitted && _this._isMounted && _this.setState({ submitted: true }); case 15: case 'end': return _context.stop(); } } }, _callee, _this2); })); return function (_x) { return _ref.apply(this, arguments); }; }(), _this.handleNonFormSubmission = function (event) { if (_this.props.onKeyDown(event) !== false) { if (event.type === 'keydown' && (event.which === 13 || event.keyCode === 13 || event.key === 'Enter')) { event.stopPropagation(); event.preventDefault(); _this.handleSubmit(event); } } }, _temp), (0, _possibleConstructorReturn3.default)(_this, _ret); } AvForm.prototype.getChildContext = function getChildContext() { var _this3 = this; return { FormCtrl: { getDefaultValue: this.getDefaultValue.bind(this), getInputState: this.getInputState.bind(this), getInput: function getInput(name) { return _this3._inputs[name]; }, getInputValue: this.getValue.bind(this), getInputs: this.getInputs.bind(this), getValues: this.getValues.bind(this), hasError: this.hasError.bind(this), isDirty: this.isDirty.bind(this), isTouched: this.isTouched.bind(this), isBad: this.isBad.bind(this), isDisabled: function isDisabled() { return _this3.props.disabled; }, isReadOnly: function isReadOnly() { return _this3.props.readOnly; }, setDirty: this.setDirty.bind(this), setTouched: this.setTouched.bind(this), setBad: this.setBad.bind(this), register: this.registerInput.bind(this), unregister: this.unregisterInput.bind(this), validate: this.validateInput.bind(this), getValidationEvent: function getValidationEvent() { return _this3.props.validationEvent; }, parent: this.context.FormCtrl || null } }; }; AvForm.prototype.componentWillUnmount = function componentWillUnmount() { this._isMounted = false; }; AvForm.prototype.componentWillMount = function componentWillMount() { this._isMounted = true; _InputContainer.prototype.componentWillMount.call(this); this._validators = {}; }; AvForm.prototype.registerInput = function registerInput(input, updater) { _InputContainer.prototype.registerInput.call(this, input, updater); if ((0, _typeof3.default)(input.validations) === 'object') { this._validators[input.props.name] = this.compileValidationRules(input, input.validations); } }; AvForm.prototype.unregisterInput = function unregisterInput(input) { _InputContainer.prototype.unregisterInput.call(this, input); delete this._validators[input.props.name]; this.setError(input.props.name, false); this.setDirty(input.props.name, false); this.setTouched(input.props.name, false); this.setBad(input.props.name, false); }; AvForm.prototype.render = function render() { var _props = this.props, Tag = _props.tag, omit1 = _props.errorMessage, omit2 = _props.model, omit3 = _props.onValidSubmit, omit4 = _props.onInvalidSubmit, omit5 = _props.validate, omit6 = _props.validateOne, omit7 = _props.validateAll, omit8 = _props.validationEvent, omit9 = _props.disabled, omit10 = _props.readOnly, omit11 = _props.beforeSubmitValidation, className = _props.className, attributes = (0, _objectWithoutProperties3.default)(_props, ['tag', 'errorMessage', 'model', 'onValidSubmit', 'onInvalidSubmit', 'validate', 'validateOne', 'validateAll', 'validationEvent', 'disabled', 'readOnly', 'beforeSubmitValidation', 'className']); var classes = (0, _classnames2.default)(className, this.state.submitted ? 'av-submitted' : false, (0, _keys2.default)(this.state.invalidInputs).length > 0 ? 'av-invalid' : 'av-valid'); if (Tag !== 'form' && Tag !== _reactstrap.Form) { attributes.onKeyDown = this.handleNonFormSubmission; } return _react2.default.createElement(Tag, (0, _extends3.default)({ noValidate: true, action: '#' }, attributes, { className: classes, onSubmit: this.handleSubmit })); }; AvForm.prototype.getInputs = function getInputs() { return this._inputs; }; AvForm.prototype.getValues = function getValues() { var _this4 = this; return (0, _keys2.default)(this._inputs).reduce(function (values, inputName) { (0, _set3.default)(values, inputName, _this4.getValue(inputName)); return values; }, {}); }; AvForm.prototype.submit = function submit() { this.handleSubmit.apply(this, arguments); }; AvForm.prototype.reset = function reset() { var _this5 = this; (0, _keys2.default)(this._inputs).forEach(function (inputName) { return _this5._inputs[inputName] && _this5._inputs[inputName].reset(); }); }; AvForm.prototype.updateInputs = function updateInputs() { var _this6 = this; if (this.throttledUpdateInputs) { this.throttledUpdateInputs(); return; } // this is just until a more intelligent way to determine which inputs need updated is implemented in v3 this.throttledUpdateInputs = (0, _throttle3.default)(function () { (0, _keys2.default)(_this6._updaters).forEach(function (inputName) { return _this6._updaters[inputName] && _this6._inputs[inputName] && _this6._updaters[inputName].call(_this6._inputs[inputName], {}); }); }, 250); this.updateInputs(); }; AvForm.prototype.validateInput = function () { var _ref3 = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee2(name) { return _regenerator2.default.wrap(function _callee2$(_context2) { while (1) { switch (_context2.prev = _context2.next) { case 0: _context2.next = 2; return this.validateOne(name, this.getValues()); case 2: case 'end': return _context2.stop(); } } }, _callee2, this); })); function validateInput(_x2) { return _ref3.apply(this, arguments); } return validateInput; }(); AvForm.prototype.getInputState = function getInputState(inputName) { var errorMessage = void 0; var error = this.isTouched(inputName) && this.hasError(inputName); var color = void 0; if (error) { errorMessage = this.state.invalidInputs[inputName]; color = 'danger'; if (!(0, _isString2.default)(errorMessage)) { errorMessage = 'This field is invalid'; } } return { color: color, error: error, errorMessage: errorMessage }; }; AvForm.prototype.hasError = function hasError(inputName) { return inputName ? !!this.state.invalidInputs[inputName] : (0, _keys2.default)(this.state.invalidInputs).length > 0; }; AvForm.prototype.isDirty = function isDirty(inputName) { return inputName ? !!this.state.dirtyInputs[inputName] : (0, _keys2.default)(this.state.dirtyInputs).length > 0; }; AvForm.prototype.isTouched = function isTouched(inputName) { return inputName ? !!this.state.touchedInputs[inputName] : (0, _keys2.default)(this.state.touchedInputs).length > 0; }; AvForm.prototype.isBad = function isBad(inputName) { return inputName ? !!this.state.badInputs[inputName] : (0, _keys2.default)(this.state.badInputs).length > 0; }; AvForm.prototype.setError = function setError(inputName) { var error = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; var _this7 = this; var errText = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : error; var update = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true; if (error && !(0, _isString2.default)(errText) && typeof errText !== 'boolean') { errText = errText + ''; } var changed = false; var currentError = this.hasError(inputName); var invalidInputs = this.state.invalidInputs; if ((invalidInputs[inputName] === undefined && !error || invalidInputs[inputName] === (errText || true)) && error === currentError) return; if (error) { invalidInputs[inputName] = errText || true; changed = true; } else { delete invalidInputs[inputName]; changed = true; } if (!changed) return; invalidInputs = (0, _extends3.default)({}, this.state.invalidInputs); this._isMounted && this.setState({ invalidInputs: invalidInputs }, function () { if (update) _this7.updateInputs(); }); }; AvForm.prototype.setDirty = function setDirty(inputs) { var _this8 = this; var dirty = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; var update = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true; var dirtyInputs = this.state.dirtyInputs; var changed = false; if (!Array.isArray(inputs)) { inputs = [inputs]; } inputs.forEach(function (inputName) { if (dirty && !dirtyInputs[inputName]) { dirtyInputs[inputName] = true; changed = true; } else if (!dirty && dirtyInputs[inputName]) { delete dirtyInputs[inputName]; changed = true; } }); if (!changed) return; dirtyInputs = (0, _extends3.default)({}, this.state.dirtyInputs); this._isMounted && this.setState({ dirtyInputs: dirtyInputs }, function () { if (update) _this8.updateInputs(); }); }; AvForm.prototype.setTouched = function setTouched(inputs) { var _this9 = this; var touched = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; var update = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true; var touchedInputs = this.state.touchedInputs; var changed = false; if (!Array.isArray(inputs)) { inputs = [inputs]; } inputs.forEach(function (inputName) { if (touched && !touchedInputs[inputName]) { touchedInputs[inputName] = true; changed = true; } else if (!touched && touchedInputs[inputName]) { delete touchedInputs[inputName]; changed = true; } }); if (!changed) return; touchedInputs = (0, _extends3.default)({}, this.state.touchedInputs); this._isMounted && this.setState({ touchedInputs: touchedInputs }, function () { if (update) _this9.updateInputs(); }); }; AvForm.prototype.setBad = function setBad(inputs) { var _this10 = this; var isBad = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; var update = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true; var badInputs = this.state.badInputs; var changed = false; if (!Array.isArray(inputs)) { inputs = [inputs]; } inputs.forEach(function (inputName) { if (isBad && !badInputs[inputName]) { badInputs[inputName] = true; changed = true; } else if (!isBad && badInputs[inputName]) { delete badInputs[inputName]; changed = true; } }); if (!changed) return; badInputs = (0, _extends3.default)({}, this.state.badInputs); this._isMounted && this.setState({ badInputs: badInputs }, function () { if (update) _this10.updateInputs(); }); }; AvForm.prototype.validateOne = function () { var _ref4 = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee3(inputName, context) { var update = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true; var input, value, validate, isValid, result, error; return _regenerator2.default.wrap(function _callee3$(_context3) { while (1) { switch (_context3.prev = _context3.next) { case 0: input = this._inputs[inputName]; if (!Array.isArray(input)) { _context3.next = 3; break; } throw new Error('Multiple inputs cannot use the same name: "' + inputName + '"'); case 3: value = (0, _get3.default)(context, inputName); validate = input.validations; isValid = true; result = void 0; error = void 0; if (!(typeof validate === 'function')) { _context3.next = 14; break; } _context3.next = 11; return validate(value, context, input); case 11: result = _context3.sent; _context3.next = 21; break; case 14: if (!((typeof validate === 'undefined' ? 'undefined' : (0, _typeof3.default)(validate)) === 'object')) { _context3.next = 20; break; } _context3.next = 17; return this._validators[inputName](value, context); case 17: result = _context3.sent; _context3.next = 21; break; case 20: result = true; case 21: if (result !== true) { isValid = false; if ((0, _isString2.default)(result)) { error = result; } } this.setError(inputName, !isValid, error, update); return _context3.abrupt('return', isValid); case 24: case 'end': return _context3.stop(); } } }, _callee3, this); })); function validateOne(_x12, _x13) { return _ref4.apply(this, arguments); } return validateOne; }(); AvForm.prototype.validateAll = function () { var _ref5 = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee4(context) { var update = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; var errors, isValid, inputName, valid, formLevelValidation; return _regenerator2.default.wrap(function _callee4$(_context4) { while (1) { switch (_context4.prev = _context4.next) { case 0: errors = []; isValid = true; _context4.t0 = _regenerator2.default.keys(this._inputs); case 3: if ((_context4.t1 = _context4.t0()).done) { _context4.next = 12; break; } inputName = _context4.t1.value; if (!this._inputs.hasOwnProperty(inputName)) { _context4.next = 10; break; } _context4.next = 8; return this.validateOne(inputName, context, update); case 8: valid = _context4.sent; if (!valid) { isValid = false; errors.push(inputName); } case 10: _context4.next = 3; break; case 12: if (this.props.validate) { formLevelValidation = this.props.validate; if (!Array.isArray(formLevelValidation)) { formLevelValidation = [formLevelValidation]; } if (!formLevelValidation.every(function (validationFn) { return validationFn(context); })) { isValid = false; errors.push('*'); } } return _context4.abrupt('return', { isValid: isValid, errors: errors }); case 14: case 'end': return _context4.stop(); } } }, _callee4, this); })); function validateAll(_x15) { return _ref5.apply(this, arguments); } return validateAll; }(); AvForm.prototype.compileValidationRules = function compileValidationRules(input, ruleProp) { var _this11 = this; return function () { var _ref6 = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee5(val, context) { var result, validations, _loop, rule; return _regenerator2.default.wrap(function _callee5$(_context5) { while (1) { switch (_context5.prev = _context5.next) { case 0: if (!_this11.isBad(input.props.name)) { _context5.next = 2; break; } return _context5.abrupt('return', false); case 2: result = true; validations = []; _loop = function _loop(rule) { /* istanbul ignore else */ if (ruleProp.hasOwnProperty(rule)) { var ruleResult = void 0; var promise = new _promise2.default(function (resolve, reject) { var callback = function callback(value) { return resolve({ value: value, rule: rule }); }; if (typeof ruleProp[rule] === 'function') { ruleResult = ruleProp[rule](val, context, input, callback); } else { if (typeof _AvValidator2.default[rule] !== 'function') { return reject(new Error('Invalid input validation rule: "' + rule + '"')); } if (ruleProp[rule].enabled === false) { ruleResult = true; } else { ruleResult = _AvValidator2.default[rule](val, context, ruleProp[rule], input, callback); } } if (ruleResult && typeof ruleResult.then === 'function') { ruleResult.then(callback); } else if (ruleResult !== undefined) { callback(ruleResult); } else { // they are using the callback } }); validations.push(promise); } }; for (rule in ruleProp) { _loop(rule); } _context5.next = 8; return _promise2.default.all(validations).then(function (results) { results.every(function (ruleResult) { if (result === true && ruleResult.value !== true) { result = (0, _isString2.default)(ruleResult.value) && ruleResult.value || getInputErrorMessage(input, ruleResult.rule) || getInputErrorMessage(_this11, ruleResult.rule) || false; } return result === true; }); }); case 8: return _context5.abrupt('return', result); case 9: case 'end': return _context5.stop(); } } }, _callee5, _this11); })); return function (_x17, _x18) { return _ref6.apply(this, arguments); }; }(); }; AvForm.prototype.getDefaultValue = function getDefaultValue(inputName) { return (0, _get3.default)(this.props.model, inputName); }; AvForm.prototype.getValue = function getValue(inputName) { var input = this._inputs[inputName]; if (!input) return undefined; if (Array.isArray(input)) { throw new Error('Multiple inputs cannot use the same name: "' + inputName + '"'); } return input.getValue(); }; return AvForm; }(_AvInputContainer2.default); AvForm.childContextTypes = { FormCtrl: _propTypes2.default.object.isRequired }; AvForm.contextTypes = { FormCtrl: _propTypes2.default.object }; AvForm.propTypes = { tag: _propTypes2.default.oneOfType([_propTypes2.default.func, _propTypes2.default.string]), className: _propTypes2.default.string, model: _propTypes2.default.object, method: _propTypes2.default.oneOf(['get', 'post']), onSubmit: _propTypes2.default.func, beforeSubmitValidation: _propTypes2.default.func, validate: _propTypes2.default.oneOfType([_propTypes2.default.func, _propTypes2.default.array]), onValidSubmit: _propTypes2.default.func, onInvalidSubmit: _propTypes2.default.func, validationEvent: _propTypes2.default.oneOfType([_propTypes2.default.oneOf(['onInput', 'onChange', 'onBlur', 'onFocus']), _propTypes2.default.arrayOf(_propTypes2.default.oneOf(['onInput', 'onChange', 'onBlur', 'onFocus']))]), errorMessage: _propTypes2.default.oneOfType([_propTypes2.default.object, _propTypes2.default.string, _propTypes2.default.node]), disabled: _propTypes2.default.bool, readOnly: _propTypes2.default.bool }; AvForm.defaultProps = { tag: _reactstrap.Form, model: {}, validationEvent: ['onChange', 'onInput'], method: 'get', onSubmit: function onSubmit() {}, onKeyDown: function onKeyDown() {}, onValidSubmit: function onValidSubmit() {}, onInvalidSubmit: function onInvalidSubmit() {} }; exports.default = AvForm;