UNPKG

@aliretail/react-materials-components

Version:
244 lines (203 loc) 7.93 kB
import _extends from "@babel/runtime/helpers/extends"; import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/objectWithoutPropertiesLoose"; var _excluded = ["value", "onChange", "rules", "containerClassName", "containerStyle"]; function _createForOfIteratorHelperLoose(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (it) return (it = it.call(o)).next.bind(it); if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; return function () { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); } function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; } import * as React from 'react'; import FormHelp from "../FormHelpExtra"; import V from '@alifd/validate'; import { uniqueId } from 'lodash'; import { usePersistFn } from 'ahooks'; import classNames from 'classnames'; /** * 获取唯一作用域的值 * @returns 作用域唯一值 */ var getUniqueScope = function getUniqueScope() { return uniqueId('PresetScope'); }; /** * 获取组件唯一值 * @returns 组件唯一值 */ var getUniqueComponentId = function getUniqueComponentId() { return uniqueId('PresetComponentId'); }; var FormObserver = /*#__PURE__*/function () { function FormObserver() { this.values = {}; this.subscribers = new Set(); } /** 注册观察者,返回值是取消注册 */ var _proto = FormObserver.prototype; _proto.register = function register(subscriber) { var _this = this; this.subscribers.add(subscriber); return function () { _this.subscribers["delete"](subscriber); }; }; _proto.setCopyValue = function setCopyValue(componentId, value) { this.values[componentId] = value; }; _proto.getCopyValue = function getCopyValue(componentId) { return this.values[componentId]; }; _proto.pass = function pass() { for (var _iterator = _createForOfIteratorHelperLoose(this.subscribers), _step; !(_step = _iterator()).done;) { var subscriber = _step.value; subscriber.reset(); } return Promise.resolve(); }; _proto.validate = function validate() { var _this2 = this; return new Promise(function (resolve, reject) { Promise.resolve().then(function () { Promise.all(Array.from(_this2.subscribers).map(function (subscriber) { var value = _this2.getCopyValue(subscriber.componentId); return subscriber.validate(value); })).then(function () { resolve(); })["catch"](function () { // form item 上的统一错误信息 reject(new Error(' ')); }); }); }); }; return FormObserver; }(); /** * Pool 中存了根据scope 获取 observer 中的所有操作 */ var Pool = function () { var observers = {}; /** * 获取一个Observer,不存在时则新建一个 */ var getFormObserver = function getFormObserver(scope) { if (!observers[scope]) { observers[scope] = new FormObserver(); } return observers[scope]; }; var validate = function validate(scope) { var observer = getFormObserver(scope); return observer.validate(); }; /** 放弃校验,直接通过 */ var pass = function pass(scope) { var observer = getFormObserver(scope); return observer.pass(); }; return { getFormObserver: getFormObserver, validate: validate, pass: pass }; }(); /** form item 上的校验规则 */ var validate = Pool.validate, pass = Pool.pass; /** * 集成表单组件的error提示 * @param FormComponent 表单组件(实现 value、onChange 的组件) * @param scope 创建校验的作用域 * @returns 带 error 提示的表单组件 */ export { validate, pass }; export var withFormError = function withFormError(FormComponent, scope) { if (scope === void 0) { scope = getUniqueScope(); } /** 对应scope 的错误信息都在这里 */ var observer = Pool.getFormObserver(scope); return function (props) { // eslint-disable-next-line react/prop-types var value = props.value, onChange = props.onChange, rules = props.rules, containerClassName = props.containerClassName, containerStyle = props.containerStyle, restProps = _objectWithoutPropertiesLoose(props, _excluded); var _React$useState = React.useState(), state = _React$useState[0], setState = _React$useState[1]; var _React$useState2 = React.useState([]), errors = _React$useState2[0], setErrors = _React$useState2[1]; var componentId = React.useRef(''); // 为什么在render中copyValue? // 其实是为了监听整个form item 的value更新,更新之后此组件会rerender if (componentId.current) { observer.setCopyValue(componentId.current, value); } React.useEffect(function () { var id = getUniqueComponentId(); observer.setCopyValue(id, value); componentId.current = id; var subscriber = { componentId: id, validate: validateValue, reset: reset }; var unregister = observer.register(subscriber); return function () { unregister(); }; }, []); var reset = usePersistFn(function () { setState === null || setState === void 0 ? void 0 : setState(undefined); setErrors === null || setErrors === void 0 ? void 0 : setErrors([]); }); var validateValue = usePersistFn(function (v) { if (rules) { return new Promise(function (resolve, reject) { var validator = new V({ value: rules }); validator.validatePromise({ value: v }).then(function (result) { /** * errors: [{ message: string, field: 'value' }] * fields: { value: [{ message: string, field: 'value' }] } */ if (result.errors) { var err = result.errors.map(function (e) { return e.message; }); setState('error'); setErrors(err); reject(err); } else { reset(); resolve(); } }); }); } else { return Promise.resolve(); } }); var handleChange = function handleChange(v) { observer.setCopyValue(componentId.current, v); for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { args[_key - 1] = arguments[_key]; } onChange === null || onChange === void 0 ? void 0 : onChange.apply(void 0, [v].concat(args)); }; return /*#__PURE__*/React.createElement("div", { className: classNames('aliretail-with-form-error', containerClassName), style: containerStyle }, /*#__PURE__*/React.createElement(FormComponent, _extends({}, restProps, { state: state, value: value, onChange: handleChange })), !!errors.length && /*#__PURE__*/React.createElement(FormHelp, { className: "aliretail-with-form-error-error", type: "error" }, errors[0])); }; };