@aliretail/react-materials-components
Version:
244 lines (203 loc) • 7.93 kB
JavaScript
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]));
};
};