UNPKG

redux-form

Version:

A higher order component decorator for forms using Redux and React

358 lines (288 loc) 15.3 kB
'use strict'; exports.__esModule = true; var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; var _actions = require('./actions'); var importedActions = _interopRequireWildcard(_actions); var _getDisplayName = require('./getDisplayName'); var _getDisplayName2 = _interopRequireDefault(_getDisplayName); var _reducer = require('./reducer'); var _deepEqual = require('deep-equal'); var _deepEqual2 = _interopRequireDefault(_deepEqual); var _bindActionData = require('./bindActionData'); var _bindActionData2 = _interopRequireDefault(_bindActionData); var _getValues = require('./getValues'); var _getValues2 = _interopRequireDefault(_getValues); var _isValid = require('./isValid'); var _isValid2 = _interopRequireDefault(_isValid); var _readFields = require('./readFields'); var _readFields2 = _interopRequireDefault(_readFields); var _handleSubmit2 = require('./handleSubmit'); var _handleSubmit3 = _interopRequireDefault(_handleSubmit2); var _asyncValidation = require('./asyncValidation'); var _asyncValidation2 = _interopRequireDefault(_asyncValidation); var _silenceEvents = require('./events/silenceEvents'); var _silenceEvents2 = _interopRequireDefault(_silenceEvents); var _silenceEvent = require('./events/silenceEvent'); var _silenceEvent2 = _interopRequireDefault(_silenceEvent); var _wrapMapDispatchToProps = require('./wrapMapDispatchToProps'); var _wrapMapDispatchToProps2 = _interopRequireDefault(_wrapMapDispatchToProps); var _wrapMapStateToProps = require('./wrapMapStateToProps'); var _wrapMapStateToProps2 = _interopRequireDefault(_wrapMapStateToProps); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; } 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; } /** * Creates a HOC that knows how to create redux-connected sub-components. */ var createHigherOrderComponent = function createHigherOrderComponent(config, isReactNative, React, connect, WrappedComponent, mapStateToProps, mapDispatchToProps, mergeProps, options) { var Component = React.Component; var PropTypes = React.PropTypes; return function (reduxMountPoint, formName, formKey, getFormState) { var ReduxForm = function (_Component) { _inherits(ReduxForm, _Component); function ReduxForm(props) { _classCallCheck(this, ReduxForm); // bind functions var _this = _possibleConstructorReturn(this, _Component.call(this, props)); _this.asyncValidate = _this.asyncValidate.bind(_this); _this.handleSubmit = _this.handleSubmit.bind(_this); _this.fields = (0, _readFields2.default)(props, {}, {}, _this.asyncValidate, isReactNative); var submitPassback = _this.props.submitPassback; submitPassback(function () { return _this.handleSubmit(); }); // wrapped in function to disallow params return _this; } ReduxForm.prototype.componentWillMount = function componentWillMount() { var _props = this.props; var fields = _props.fields; var form = _props.form; var initialize = _props.initialize; var initialValues = _props.initialValues; if (initialValues && !form._initialized) { initialize(initialValues, fields); } }; ReduxForm.prototype.componentWillReceiveProps = function componentWillReceiveProps(nextProps) { if (!(0, _deepEqual2.default)(this.props.fields, nextProps.fields) || !(0, _deepEqual2.default)(this.props.form, nextProps.form, { strict: true })) { this.fields = (0, _readFields2.default)(nextProps, this.props, this.fields, this.asyncValidate, isReactNative); } if (!(0, _deepEqual2.default)(this.props.initialValues, nextProps.initialValues)) { this.props.initialize(nextProps.initialValues, nextProps.fields); } }; ReduxForm.prototype.componentWillUnmount = function componentWillUnmount() { if (config.destroyOnUnmount) { this.props.destroy(); } }; ReduxForm.prototype.asyncValidate = function asyncValidate(name, value) { var _this2 = this; var _props2 = this.props; var asyncValidate = _props2.asyncValidate; var dispatch = _props2.dispatch; var fields = _props2.fields; var form = _props2.form; var startAsyncValidation = _props2.startAsyncValidation; var stopAsyncValidation = _props2.stopAsyncValidation; var validate = _props2.validate; var isSubmitting = !name; if (asyncValidate) { var _ret = function () { var values = (0, _getValues2.default)(fields, form); if (name) { values[name] = value; } var syncErrors = validate(values, _this2.props); var allPristine = _this2.fields._meta.allPristine; var initialized = form._initialized; // if blur validating, only run async validate if sync validation passes // and submitting (not blur validation) or form is dirty or form was never initialized var syncValidationPasses = isSubmitting || (0, _isValid2.default)(syncErrors[name]); if (syncValidationPasses && (isSubmitting || !allPristine || !initialized)) { return { v: (0, _asyncValidation2.default)(function () { return asyncValidate(values, dispatch, _this2.props); }, startAsyncValidation, stopAsyncValidation, name) }; } }(); if (typeof _ret === "object") return _ret.v; } }; ReduxForm.prototype.handleSubmit = function handleSubmit(submitOrEvent) { var _this3 = this; var _props3 = this.props; var onSubmit = _props3.onSubmit; var fields = _props3.fields; var form = _props3.form; var check = function check(submit) { if (!submit || typeof submit !== 'function') { throw new Error('You must either pass handleSubmit() an onSubmit function or pass onSubmit as a prop'); } return submit; }; return !submitOrEvent || (0, _silenceEvent2.default)(submitOrEvent) ? // submitOrEvent is an event: fire submit (0, _handleSubmit3.default)(check(onSubmit), (0, _getValues2.default)(fields, form), this.props, this.asyncValidate) : // submitOrEvent is the submit function: return deferred submit thunk (0, _silenceEvents2.default)(function () { return (0, _handleSubmit3.default)(check(submitOrEvent), (0, _getValues2.default)(fields, form), _this3.props, _this3.asyncValidate); }); }; ReduxForm.prototype.render = function render() { var _this4 = this, _ref; var allFields = this.fields; var _props4 = this.props; var addArrayValue = _props4.addArrayValue; var asyncBlurFields = _props4.asyncBlurFields; var blur = _props4.blur; var change = _props4.change; var destroy = _props4.destroy; var focus = _props4.focus; var fields = _props4.fields; var form = _props4.form; var initialValues = _props4.initialValues; var initialize = _props4.initialize; var onSubmit = _props4.onSubmit; var propNamespace = _props4.propNamespace; var reset = _props4.reset; var removeArrayValue = _props4.removeArrayValue; var returnRejectedSubmitPromise = _props4.returnRejectedSubmitPromise; var startAsyncValidation = _props4.startAsyncValidation; var startSubmit = _props4.startSubmit; var stopAsyncValidation = _props4.stopAsyncValidation; var stopSubmit = _props4.stopSubmit; var submitFailed = _props4.submitFailed; var swapArrayValues = _props4.swapArrayValues; var touch = _props4.touch; var untouch = _props4.untouch; var validate = _props4.validate; var passableProps = _objectWithoutProperties(_props4, ['addArrayValue', 'asyncBlurFields', 'blur', 'change', 'destroy', 'focus', 'fields', 'form', 'initialValues', 'initialize', 'onSubmit', 'propNamespace', 'reset', 'removeArrayValue', 'returnRejectedSubmitPromise', 'startAsyncValidation', 'startSubmit', 'stopAsyncValidation', 'stopSubmit', 'submitFailed', 'swapArrayValues', 'touch', 'untouch', 'validate']); // eslint-disable-line no-redeclare var _allFields$_meta = allFields._meta; var allPristine = _allFields$_meta.allPristine; var allValid = _allFields$_meta.allValid; var errors = _allFields$_meta.errors; var formError = _allFields$_meta.formError; var values = _allFields$_meta.values; var props = { // State: active: form._active, asyncValidating: form._asyncValidating, dirty: !allPristine, error: formError, errors: errors, fields: allFields, formKey: formKey, invalid: !allValid, pristine: allPristine, submitting: form._submitting, submitFailed: form._submitFailed, valid: allValid, values: values, // Actions: asyncValidate: (0, _silenceEvents2.default)(function () { return _this4.asyncValidate(); }), // ^ doesn't just pass this.asyncValidate to disallow values passing destroyForm: (0, _silenceEvents2.default)(destroy), handleSubmit: this.handleSubmit, initializeForm: (0, _silenceEvents2.default)(function (initValues) { return initialize(initValues, fields); }), resetForm: (0, _silenceEvents2.default)(reset), touch: (0, _silenceEvents2.default)(function () { return touch.apply(undefined, arguments); }), touchAll: (0, _silenceEvents2.default)(function () { return touch.apply(undefined, fields); }), untouch: (0, _silenceEvents2.default)(function () { return untouch.apply(undefined, arguments); }), untouchAll: (0, _silenceEvents2.default)(function () { return untouch.apply(undefined, fields); }) }; var passedProps = propNamespace ? (_ref = {}, _ref[propNamespace] = props, _ref) : props; return React.createElement(WrappedComponent, _extends({}, passableProps, passedProps)); }; return ReduxForm; }(Component); ReduxForm.displayName = 'ReduxForm(' + (0, _getDisplayName2.default)(WrappedComponent) + ')'; ReduxForm.WrappedComponent = WrappedComponent; ReduxForm.propTypes = { // props: asyncBlurFields: PropTypes.arrayOf(PropTypes.string), asyncValidate: PropTypes.func, dispatch: PropTypes.func.isRequired, fields: PropTypes.arrayOf(PropTypes.string).isRequired, form: PropTypes.object, initialValues: PropTypes.any, onSubmit: PropTypes.func, propNamespace: PropTypes.string, readonly: PropTypes.bool, returnRejectedSubmitPromise: PropTypes.bool, submitPassback: PropTypes.func.isRequired, validate: PropTypes.func, // actions: addArrayValue: PropTypes.func.isRequired, blur: PropTypes.func.isRequired, change: PropTypes.func.isRequired, destroy: PropTypes.func.isRequired, focus: PropTypes.func.isRequired, initialize: PropTypes.func.isRequired, removeArrayValue: PropTypes.func.isRequired, reset: PropTypes.func.isRequired, startAsyncValidation: PropTypes.func.isRequired, startSubmit: PropTypes.func.isRequired, stopAsyncValidation: PropTypes.func.isRequired, stopSubmit: PropTypes.func.isRequired, submitFailed: PropTypes.func.isRequired, swapArrayValues: PropTypes.func.isRequired, touch: PropTypes.func.isRequired, untouch: PropTypes.func.isRequired }; ReduxForm.defaultProps = { asyncBlurFields: [], form: _reducer.initialState, readonly: false, returnRejectedSubmitPromise: false, validate: function validate() { return {}; } }; // bind touch flags to blur and change var unboundActions = _extends({}, importedActions, { blur: (0, _bindActionData2.default)(importedActions.blur, { touch: !!config.touchOnBlur }), change: (0, _bindActionData2.default)(importedActions.change, { touch: !!config.touchOnChange }) }); // make redux connector with or without form key var decorate = formKey !== undefined && formKey !== null ? connect((0, _wrapMapStateToProps2.default)(mapStateToProps, function (state) { var formState = getFormState(state, reduxMountPoint); if (!formState) { throw new Error('You need to mount the redux-form reducer at "' + reduxMountPoint + '"'); } return formState && formState[formName] && formState[formName][formKey]; }), (0, _wrapMapDispatchToProps2.default)(mapDispatchToProps, (0, _bindActionData2.default)(unboundActions, { form: formName, key: formKey })), mergeProps, options) : connect((0, _wrapMapStateToProps2.default)(mapStateToProps, function (state) { var formState = getFormState(state, reduxMountPoint); if (!formState) { throw new Error('You need to mount the redux-form reducer at "' + reduxMountPoint + '"'); } return formState && formState[formName]; }), (0, _wrapMapDispatchToProps2.default)(mapDispatchToProps, (0, _bindActionData2.default)(unboundActions, { form: formName })), mergeProps, options); return decorate(ReduxForm); }; }; exports.default = createHigherOrderComponent;