UNPKG

react-formian

Version:

A React framework for easily creating and handling controlled forms

344 lines (288 loc) 11.4 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); var _injectCSS = require('./injectCSS'); var _injectCSS2 = _interopRequireDefault(_injectCSS); var _react = require('react'); var _react2 = _interopRequireDefault(_react); var _propTypes = require('prop-types'); var _propTypes2 = _interopRequireDefault(_propTypes); var _validators = require('./validators'); var _validators2 = _interopRequireDefault(_validators); var _formatters = require('./formatters'); var _formatters2 = _interopRequireDefault(_formatters); var _Reset = require('./Buttons/Reset'); var _Reset2 = _interopRequireDefault(_Reset); var _Submit = require('./Buttons/Submit'); var _Submit2 = _interopRequireDefault(_Submit); var _Fieldset = require('./common/Fieldset'); var _Fieldset2 = _interopRequireDefault(_Fieldset); var _Inputs = require('./Inputs'); var _Inputs2 = _interopRequireDefault(_Inputs); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } var Recaptcha = _Inputs2.default[_Inputs2.default.length - 1]; var Form = function (_Component) { _inherits(Form, _Component); function Form(props) { _classCallCheck(this, Form); var _this = _possibleConstructorReturn(this, (Form.__proto__ || Object.getPrototypeOf(Form)).call(this, props)); _this.addHandlersToChild = _this.addHandlersToChild.bind(_this); _this.renderChildren = _this.renderChildren.bind(_this); _this.autoSubmit = _this.autoSubmit.bind(_this); _this.onChange = _this.onChange.bind(_this); _this.onBlur = _this.onBlur.bind(_this); _this.onFocus = _this.onFocus.bind(_this); _this.recaptcha = _this.recaptcha.bind(_this); _this.flagAllErrors = _this.flagAllErrors.bind(_this); _this.resetForm = _this.resetForm.bind(_this); _this.isDefaultState = _this.isDefaultState.bind(_this); _this.onSubmit = _this.onSubmit.bind(_this); _this.formatters = _formatters2.default; _this.validators = _validators2.default; if (props.customStyles !== false) (0, _injectCSS2.default)(); _this.initialState = { disabled: !_this.props.noValidate, formData: {} }; _this.mapInputsToState(props.children); _this.formDataKeys = Object.keys(_this.initialState.formData); _this.state = Object.assign({}, _this.initialState); return _this; } _createClass(Form, [{ key: 'mapInputsToState', value: function mapInputsToState(children) { var _this2 = this; _react.Children.map(children, function (child) { if (!child) return;else if (child.type === Recaptcha) { _this2.initialState.formData.recaptcha = false; } else if (child.type === _Fieldset2.default || child.type === 'fieldset') { _this2.mapInputsToState(child.props.children); } else if (_Inputs2.default.includes(child.type)) { // discover the dataset object key var key = child.props.name; // set prevalidated for marked inputs; otherwise set an appropriate validator function if (!child.props.required) { _this2.validators[key] = _this2.validators.prevalidated; } else { _this2.setCheckerForChild(child, 'validators'); } _this2.setCheckerForChild(child, 'formatters'); _this2.setInitialStateForChild(child); } }); } }, { key: 'setCheckerForChild', value: function setCheckerForChild(child, set, setOff) { var _child$props = child.props, name = _child$props.name, type = _child$props.type, defaultValue = _child$props.defaultValue; // tinyInt rule if (child.props.tinyInt && set === 'formatters' && (type === 'onoff' || type === 'checkbox')) { this[set][name] = this[set].tinyInt; } else { this[set][name] = child.props[set] // custom || this[set][name.toLowerCase()] // by field name || this[set][child.props.type.toLowerCase()] // by type ; } } }, { key: 'setInitialStateForChild', value: function setInitialStateForChild(child) { var _child$props2 = child.props, name = _child$props2.name, options = _child$props2.options, defaultValue = _child$props2.defaultValue; var target = { value: defaultValue, checked: defaultValue }; if (options) target.value = options[defaultValue]; this.initialState.formData[name] = this.formatters[name](target); } }, { key: 'addHandlersToChild', value: function addHandlersToChild(child, tabIndex) { if (_Inputs2.default.includes(child.type)) { return _react2.default.cloneElement(child, { tabIndex: tabIndex, onChange: child.type === Recaptcha ? this.recaptcha : this.onChange, onBlur: this.onBlur, onFocus: this.onFocus, dataset: this.state.formData, required: child.required || true }); } if (child.type === _Submit2.default) { return _react2.default.cloneElement(child, { tabIndex: tabIndex, disabled: this.state.disabled, flagAllErrors: this.flagAllErrors }); } if (child.type === _Reset2.default) { return _react2.default.cloneElement(child, { tabIndex: tabIndex, disabled: this.isDefaultState(), resetForm: this.resetForm }); } return child; } }, { key: 'renderChildren', value: function renderChildren() { var _this3 = this; var tabIndex = 1; return _react.Children.map(this.props.children, function (child) { if (!child) return; if (child.type === _Fieldset2.default || child.type === 'fieldset') { return _react2.default.cloneElement(child, { children: _react.Children.map(child.props.children, function (child) { return _this3.addHandlersToChild(child, tabIndex++); }) }); } if (_Inputs2.default.includes(child.type)) { return _this3.addHandlersToChild(child, tabIndex++); } return child; }); } }, { key: 'isDefaultState', value: function isDefaultState() { for (var i = 0; i < this.formDataKeys.length; i++) { if (this.initialState.formData[this.formDataKeys[i]] !== this.state.formData[this.formDataKeys[i]]) { return false; } } return true; } }, { key: 'onChange', value: function onChange(evt) { var key = evt.target.id; if (evt.target.type === 'radio') key = key.split('@@')[1]; var formData = Object.assign({}, this.state.formData, _defineProperty({}, key, this.formatters[key] ? this.formatters[key](evt.target) : evt.target.value)); if (!this.props.noValidate) this.checkForm(formData); if (this.props.submitOnChange) this.autoSubmit(); } // if left field with an error, flag it }, { key: 'onBlur', value: function onBlur(evt) { var formData = this.state.formData; var key = evt.target.id; var data = formData[key]; if (this.validators[key] && !this.validators[key](formData[key])) { evt.target.classList.add('error'); evt.target.nextSibling.classList.add('error'); } } // if focusing on an err'd field, clear the ErrorPage }, { key: 'onFocus', value: function onFocus(evt) { evt.target.classList.remove('error'); evt.target.nextSibling.classList.remove('error'); } }, { key: 'onSubmit', value: function onSubmit(evt) { evt.preventDefault(); if (this.state.disabled) this.flagAllErrors();else this.props.onSubmit.call(this, this.state.formData); } }, { key: 'recaptcha', value: function recaptcha(value) { var formData = Object.assign({}, this.state.formData, { recaptcha: value }); if (!this.props.noValidate) this.checkForm(formData); } }, { key: 'checkForm', value: function checkForm(formData) { var disabled = false; var key = void 0; for (var i = 0; i < this.formDataKeys.length; i++) { key = this.formDataKeys[i]; if (this.validators[key] && !this.validators[key](formData[key])) { disabled = true; break; } } this.setState({ disabled: disabled, formData: formData }); } }, { key: 'resetForm', value: function resetForm(evt) { evt.preventDefault(); this.setState(Object.assign({}, this.initialState)); for (var i = 0; i < this.formDataKeys.length; i++) { document.getElementById(this.formDataKeys[i]).dispatchEvent(new Event('blur')); } } }, { key: 'flagAllErrors', value: function flagAllErrors() { if (!this.state.disabled) return; var target = void 0; for (var i = 0; i < this.formDataKeys.length; i++) { target = document.getElementById(this.formDataKeys[i]); target.classList.remove('error'); target.nextSibling.classList.remove('error'); } } }, { key: 'autoSubmit', value: function autoSubmit() { var _this4 = this; clearTimeout(this.submitTimeout); this.submitTimeout = setTimeout(function () { _this4.onSubmit(new Event('synthetic', { bubbles: false, cancelable: true })); }, 2000); } }, { key: 'componentWillUnmount', value: function componentWillUnmount() { if (this.submitTimeout) { clearTimeout(this.submitTimeout); this.onSubmit(new Event('synthetic', { bubbles: false, cancelable: true })); } } }, { key: 'render', value: function render() { return _react2.default.createElement( 'form', { id: this.props.id, className: 'formian-form ' + this.props.className, onSubmit: this.onSubmit, style: this.props.style, disabled: this.state.disabled }, this.renderChildren() ); } }]); return Form; }(_react.Component); Form.defaultProps = { id: "", className: "", autoComplete: "on", noValidate: false, submitOnChange: false }; var Formian = _Inputs2.default.reduce(function (formian, input) { formian[input.name] = input; return formian; }, { Form: Form, Submit: _Submit2.default, Reset: _Reset2.default, Fieldset: _Fieldset2.default }); exports.default = Formian;