Form.js 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394
  1. "use strict";
  2. var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
  3. Object.defineProperty(exports, "__esModule", {
  4. value: true
  5. });
  6. exports.formProps = exports.default = void 0;
  7. var _vue = require("vue");
  8. var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
  9. var _typeof2 = _interopRequireDefault(require("@babel/runtime/helpers/typeof"));
  10. var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
  11. var _objectSpread2 = _interopRequireDefault(require("@babel/runtime/helpers/objectSpread2"));
  12. var _vueTypes = _interopRequireDefault(require("../_util/vue-types"));
  13. var _classNames2 = _interopRequireDefault(require("../_util/classNames"));
  14. var _warning = _interopRequireDefault(require("../_util/warning"));
  15. var _FormItem = _interopRequireDefault(require("./FormItem"));
  16. var _valueUtil = require("./utils/valueUtil");
  17. var _messages = require("./utils/messages");
  18. var _asyncUtil = require("./utils/asyncUtil");
  19. var _typeUtil = require("./utils/typeUtil");
  20. var _isEqual = _interopRequireDefault(require("lodash/isEqual"));
  21. var _scrollIntoViewIfNeeded = _interopRequireDefault(require("scroll-into-view-if-needed"));
  22. var _initDefaultProps = _interopRequireDefault(require("../_util/props-util/initDefaultProps"));
  23. var _type = require("../_util/type");
  24. var _useSize = require("../_util/hooks/useSize");
  25. var _useConfigInject2 = _interopRequireDefault(require("../_util/hooks/useConfigInject"));
  26. var _context = require("./context");
  27. var _useForm = _interopRequireDefault(require("./useForm"));
  28. var _context2 = require("../config-provider/context");
  29. var formProps = function formProps() {
  30. return {
  31. layout: _vueTypes.default.oneOf((0, _type.tuple)('horizontal', 'inline', 'vertical')),
  32. labelCol: {
  33. type: Object
  34. },
  35. wrapperCol: {
  36. type: Object
  37. },
  38. colon: {
  39. type: Boolean,
  40. default: undefined
  41. },
  42. labelAlign: _vueTypes.default.oneOf((0, _type.tuple)('left', 'right')),
  43. labelWrap: {
  44. type: Boolean,
  45. default: undefined
  46. },
  47. prefixCls: String,
  48. requiredMark: {
  49. type: [String, Boolean],
  50. default: undefined
  51. },
  52. /** @deprecated Will warning in future branch. Pls use `requiredMark` instead. */
  53. hideRequiredMark: {
  54. type: Boolean,
  55. default: undefined
  56. },
  57. model: _vueTypes.default.object,
  58. rules: {
  59. type: Object
  60. },
  61. validateMessages: {
  62. type: Object,
  63. default: undefined
  64. },
  65. validateOnRuleChange: {
  66. type: Boolean,
  67. default: undefined
  68. },
  69. // 提交失败自动滚动到第一个错误字段
  70. scrollToFirstError: {
  71. type: [Boolean, Object]
  72. },
  73. onSubmit: Function,
  74. name: String,
  75. validateTrigger: {
  76. type: [String, Array]
  77. },
  78. size: {
  79. type: String
  80. },
  81. onValuesChange: {
  82. type: Function
  83. },
  84. onFieldsChange: {
  85. type: Function
  86. },
  87. onFinish: {
  88. type: Function
  89. },
  90. onFinishFailed: {
  91. type: Function
  92. },
  93. onValidate: {
  94. type: Function
  95. }
  96. };
  97. };
  98. exports.formProps = formProps;
  99. function isEqualName(name1, name2) {
  100. return (0, _isEqual.default)((0, _typeUtil.toArray)(name1), (0, _typeUtil.toArray)(name2));
  101. }
  102. var Form = (0, _vue.defineComponent)({
  103. compatConfig: {
  104. MODE: 3
  105. },
  106. name: 'AForm',
  107. inheritAttrs: false,
  108. props: (0, _initDefaultProps.default)(formProps(), {
  109. layout: 'horizontal',
  110. hideRequiredMark: false,
  111. colon: true
  112. }),
  113. Item: _FormItem.default,
  114. useForm: _useForm.default,
  115. // emits: ['finishFailed', 'submit', 'finish', 'validate'],
  116. setup: function setup(props, _ref) {
  117. var emit = _ref.emit,
  118. slots = _ref.slots,
  119. expose = _ref.expose,
  120. attrs = _ref.attrs;
  121. var size = (0, _useSize.useInjectSize)(props);
  122. var _useConfigInject = (0, _useConfigInject2.default)('form', props),
  123. prefixCls = _useConfigInject.prefixCls,
  124. direction = _useConfigInject.direction,
  125. contextForm = _useConfigInject.form;
  126. var requiredMark = (0, _vue.computed)(function () {
  127. return props.requiredMark === '' || props.requiredMark;
  128. });
  129. var mergedRequiredMark = (0, _vue.computed)(function () {
  130. var _contextForm$value;
  131. if (requiredMark.value !== undefined) {
  132. return requiredMark.value;
  133. }
  134. if (contextForm && ((_contextForm$value = contextForm.value) === null || _contextForm$value === void 0 ? void 0 : _contextForm$value.requiredMark) !== undefined) {
  135. return contextForm.value.requiredMark;
  136. }
  137. if (props.hideRequiredMark) {
  138. return false;
  139. }
  140. return true;
  141. });
  142. var mergedColon = (0, _vue.computed)(function () {
  143. var _props$colon, _contextForm$value2;
  144. return (_props$colon = props.colon) !== null && _props$colon !== void 0 ? _props$colon : (_contextForm$value2 = contextForm.value) === null || _contextForm$value2 === void 0 ? void 0 : _contextForm$value2.colon;
  145. });
  146. var _useInjectGlobalForm = (0, _context2.useInjectGlobalForm)(),
  147. globalValidateMessages = _useInjectGlobalForm.validateMessages;
  148. var validateMessages = (0, _vue.computed)(function () {
  149. return (0, _objectSpread2.default)((0, _objectSpread2.default)((0, _objectSpread2.default)({}, _messages.defaultValidateMessages), globalValidateMessages.value), props.validateMessages);
  150. });
  151. var formClassName = (0, _vue.computed)(function () {
  152. var _classNames;
  153. return (0, _classNames2.default)(prefixCls.value, (_classNames = {}, (0, _defineProperty2.default)(_classNames, "".concat(prefixCls.value, "-").concat(props.layout), true), (0, _defineProperty2.default)(_classNames, "".concat(prefixCls.value, "-hide-required-mark"), mergedRequiredMark.value === false), (0, _defineProperty2.default)(_classNames, "".concat(prefixCls.value, "-rtl"), direction.value === 'rtl'), (0, _defineProperty2.default)(_classNames, "".concat(prefixCls.value, "-").concat(size.value), size.value), _classNames));
  154. });
  155. var lastValidatePromise = (0, _vue.ref)();
  156. var fields = {};
  157. var addField = function addField(eventKey, field) {
  158. fields[eventKey] = field;
  159. };
  160. var removeField = function removeField(eventKey) {
  161. delete fields[eventKey];
  162. };
  163. var getFieldsByNameList = function getFieldsByNameList(nameList) {
  164. var provideNameList = !!nameList;
  165. var namePathList = provideNameList ? (0, _typeUtil.toArray)(nameList).map(_valueUtil.getNamePath) : [];
  166. if (!provideNameList) {
  167. return Object.values(fields);
  168. } else {
  169. return Object.values(fields).filter(function (field) {
  170. return namePathList.findIndex(function (namePath) {
  171. return isEqualName(namePath, field.fieldName.value);
  172. }) > -1;
  173. });
  174. }
  175. };
  176. var resetFields = function resetFields(name) {
  177. if (!props.model) {
  178. (0, _warning.default)(false, 'Form', 'model is required for resetFields to work.');
  179. return;
  180. }
  181. getFieldsByNameList(name).forEach(function (field) {
  182. field.resetField();
  183. });
  184. };
  185. var clearValidate = function clearValidate(name) {
  186. getFieldsByNameList(name).forEach(function (field) {
  187. field.clearValidate();
  188. });
  189. };
  190. var handleFinishFailed = function handleFinishFailed(errorInfo) {
  191. var scrollToFirstError = props.scrollToFirstError;
  192. emit('finishFailed', errorInfo);
  193. if (scrollToFirstError && errorInfo.errorFields.length) {
  194. var scrollToFieldOptions = {};
  195. if ((0, _typeof2.default)(scrollToFirstError) === 'object') {
  196. scrollToFieldOptions = scrollToFirstError;
  197. }
  198. scrollToField(errorInfo.errorFields[0].name, scrollToFieldOptions);
  199. }
  200. };
  201. var validate = function validate() {
  202. return validateField.apply(void 0, arguments);
  203. };
  204. var scrollToField = function scrollToField(name) {
  205. var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
  206. var fields = getFieldsByNameList(name ? [name] : undefined);
  207. if (fields.length) {
  208. var fieldId = fields[0].fieldId.value;
  209. var node = fieldId ? document.getElementById(fieldId) : null;
  210. if (node) {
  211. (0, _scrollIntoViewIfNeeded.default)(node, (0, _objectSpread2.default)({
  212. scrollMode: 'if-needed',
  213. block: 'nearest'
  214. }, options));
  215. }
  216. }
  217. };
  218. // eslint-disable-next-line no-unused-vars
  219. var getFieldsValue = function getFieldsValue() {
  220. var nameList = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
  221. if (nameList === true) {
  222. var allNameList = [];
  223. Object.values(fields).forEach(function (_ref2) {
  224. var namePath = _ref2.namePath;
  225. allNameList.push(namePath.value);
  226. });
  227. return (0, _valueUtil.cloneByNamePathList)(props.model, allNameList);
  228. } else {
  229. return (0, _valueUtil.cloneByNamePathList)(props.model, nameList);
  230. }
  231. };
  232. var validateFields = function validateFields(nameList, options) {
  233. (0, _warning.default)(!(nameList instanceof Function), 'Form', 'validateFields/validateField/validate not support callback, please use promise instead');
  234. if (!props.model) {
  235. (0, _warning.default)(false, 'Form', 'model is required for validateFields to work.');
  236. return Promise.reject('Form `model` is required for validateFields to work.');
  237. }
  238. var provideNameList = !!nameList;
  239. var namePathList = provideNameList ? (0, _typeUtil.toArray)(nameList).map(_valueUtil.getNamePath) : [];
  240. // Collect result in promise list
  241. var promiseList = [];
  242. Object.values(fields).forEach(function (field) {
  243. var _field$rules;
  244. // Add field if not provide `nameList`
  245. if (!provideNameList) {
  246. namePathList.push(field.namePath.value);
  247. }
  248. // Skip if without rule
  249. if (!((_field$rules = field.rules) !== null && _field$rules !== void 0 && _field$rules.value.length)) {
  250. return;
  251. }
  252. var fieldNamePath = field.namePath.value;
  253. // Add field validate rule in to promise list
  254. if (!provideNameList || (0, _valueUtil.containsNamePath)(namePathList, fieldNamePath)) {
  255. var promise = field.validateRules((0, _objectSpread2.default)({
  256. validateMessages: validateMessages.value
  257. }, options));
  258. // Wrap promise with field
  259. promiseList.push(promise.then(function () {
  260. return {
  261. name: fieldNamePath,
  262. errors: [],
  263. warnings: []
  264. };
  265. }).catch(function (ruleErrors) {
  266. var mergedErrors = [];
  267. var mergedWarnings = [];
  268. ruleErrors.forEach(function (_ref3) {
  269. var warningOnly = _ref3.rule.warningOnly,
  270. errors = _ref3.errors;
  271. if (warningOnly) {
  272. mergedWarnings.push.apply(mergedWarnings, (0, _toConsumableArray2.default)(errors));
  273. } else {
  274. mergedErrors.push.apply(mergedErrors, (0, _toConsumableArray2.default)(errors));
  275. }
  276. });
  277. if (mergedErrors.length) {
  278. return Promise.reject({
  279. name: fieldNamePath,
  280. errors: mergedErrors,
  281. warnings: mergedWarnings
  282. });
  283. }
  284. return {
  285. name: fieldNamePath,
  286. errors: mergedErrors,
  287. warnings: mergedWarnings
  288. };
  289. }));
  290. }
  291. });
  292. var summaryPromise = (0, _asyncUtil.allPromiseFinish)(promiseList);
  293. lastValidatePromise.value = summaryPromise;
  294. var returnPromise = summaryPromise.then(function () {
  295. if (lastValidatePromise.value === summaryPromise) {
  296. return Promise.resolve(getFieldsValue(namePathList));
  297. }
  298. return Promise.reject([]);
  299. }).catch(function (results) {
  300. var errorList = results.filter(function (result) {
  301. return result && result.errors.length;
  302. });
  303. return Promise.reject({
  304. values: getFieldsValue(namePathList),
  305. errorFields: errorList,
  306. outOfDate: lastValidatePromise.value !== summaryPromise
  307. });
  308. });
  309. // Do not throw in console
  310. returnPromise.catch(function (e) {
  311. return e;
  312. });
  313. return returnPromise;
  314. };
  315. var validateField = function validateField() {
  316. return validateFields.apply(void 0, arguments);
  317. };
  318. var handleSubmit = function handleSubmit(e) {
  319. e.preventDefault();
  320. e.stopPropagation();
  321. emit('submit', e);
  322. if (props.model) {
  323. var res = validateFields();
  324. res.then(function (values) {
  325. emit('finish', values);
  326. }).catch(function (errors) {
  327. handleFinishFailed(errors);
  328. });
  329. }
  330. };
  331. expose({
  332. resetFields: resetFields,
  333. clearValidate: clearValidate,
  334. validateFields: validateFields,
  335. getFieldsValue: getFieldsValue,
  336. validate: validate,
  337. scrollToField: scrollToField
  338. });
  339. (0, _context.useProvideForm)({
  340. model: (0, _vue.computed)(function () {
  341. return props.model;
  342. }),
  343. name: (0, _vue.computed)(function () {
  344. return props.name;
  345. }),
  346. labelAlign: (0, _vue.computed)(function () {
  347. return props.labelAlign;
  348. }),
  349. labelCol: (0, _vue.computed)(function () {
  350. return props.labelCol;
  351. }),
  352. labelWrap: (0, _vue.computed)(function () {
  353. return props.labelWrap;
  354. }),
  355. wrapperCol: (0, _vue.computed)(function () {
  356. return props.wrapperCol;
  357. }),
  358. vertical: (0, _vue.computed)(function () {
  359. return props.layout === 'vertical';
  360. }),
  361. colon: mergedColon,
  362. requiredMark: mergedRequiredMark,
  363. validateTrigger: (0, _vue.computed)(function () {
  364. return props.validateTrigger;
  365. }),
  366. rules: (0, _vue.computed)(function () {
  367. return props.rules;
  368. }),
  369. addField: addField,
  370. removeField: removeField,
  371. onValidate: function onValidate(name, status, errors) {
  372. emit('validate', name, status, errors);
  373. },
  374. validateMessages: validateMessages
  375. });
  376. (0, _vue.watch)(function () {
  377. return props.rules;
  378. }, function () {
  379. if (props.validateOnRuleChange) {
  380. validateFields();
  381. }
  382. });
  383. return function () {
  384. var _slots$default;
  385. return (0, _vue.createVNode)("form", (0, _objectSpread2.default)((0, _objectSpread2.default)({}, attrs), {}, {
  386. "onSubmit": handleSubmit,
  387. "class": [formClassName.value, attrs.class]
  388. }), [(_slots$default = slots.default) === null || _slots$default === void 0 ? void 0 : _slots$default.call(slots)]);
  389. };
  390. }
  391. });
  392. var _default = Form;
  393. exports.default = _default;