FormItem.js 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402
  1. "use strict";
  2. var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
  3. Object.defineProperty(exports, "__esModule", {
  4. value: true
  5. });
  6. exports.formItemProps = exports.default = void 0;
  7. var _vue = require("vue");
  8. var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
  9. var _objectSpread2 = _interopRequireDefault(require("@babel/runtime/helpers/objectSpread2"));
  10. var _cloneDeep = _interopRequireDefault(require("lodash/cloneDeep"));
  11. var _vueTypes = _interopRequireDefault(require("../_util/vue-types"));
  12. var _Row = _interopRequireDefault(require("../grid/Row"));
  13. var _propsUtil = require("../_util/props-util");
  14. var _validateUtil = require("./utils/validateUtil");
  15. var _valueUtil = require("./utils/valueUtil");
  16. var _typeUtil = require("./utils/typeUtil");
  17. var _warning = require("../vc-util/warning");
  18. var _find = _interopRequireDefault(require("lodash/find"));
  19. var _type = require("../_util/type");
  20. var _useConfigInject2 = _interopRequireDefault(require("../_util/hooks/useConfigInject"));
  21. var _context = require("./context");
  22. var _FormItemLabel = _interopRequireDefault(require("./FormItemLabel"));
  23. var _FormItemInput = _interopRequireDefault(require("./FormItemInput"));
  24. var _FormItemContext = require("./FormItemContext");
  25. var _useDebounce = _interopRequireDefault(require("./utils/useDebounce"));
  26. var ValidateStatuses = (0, _type.tuple)('success', 'warning', 'error', 'validating', '');
  27. function getPropByPath(obj, namePathList, strict) {
  28. var tempObj = obj;
  29. var keyArr = namePathList;
  30. var i = 0;
  31. try {
  32. for (var len = keyArr.length; i < len - 1; ++i) {
  33. if (!tempObj && !strict) break;
  34. var key = keyArr[i];
  35. if (key in tempObj) {
  36. tempObj = tempObj[key];
  37. } else {
  38. if (strict) {
  39. throw Error('please transfer a valid name path to form item!');
  40. }
  41. break;
  42. }
  43. }
  44. if (strict && !tempObj) {
  45. throw Error('please transfer a valid name path to form item!');
  46. }
  47. } catch (error) {
  48. console.error('please transfer a valid name path to form item!');
  49. }
  50. return {
  51. o: tempObj,
  52. k: keyArr[i],
  53. v: tempObj ? tempObj[keyArr[i]] : undefined
  54. };
  55. }
  56. var formItemProps = function formItemProps() {
  57. return {
  58. htmlFor: String,
  59. prefixCls: String,
  60. label: _vueTypes.default.any,
  61. help: _vueTypes.default.any,
  62. extra: _vueTypes.default.any,
  63. labelCol: {
  64. type: Object
  65. },
  66. wrapperCol: {
  67. type: Object
  68. },
  69. hasFeedback: {
  70. type: Boolean,
  71. default: false
  72. },
  73. colon: {
  74. type: Boolean,
  75. default: undefined
  76. },
  77. labelAlign: _vueTypes.default.oneOf((0, _type.tuple)('left', 'right')),
  78. prop: {
  79. type: [String, Number, Array]
  80. },
  81. name: {
  82. type: [String, Number, Array]
  83. },
  84. rules: [Array, Object],
  85. autoLink: {
  86. type: Boolean,
  87. default: true
  88. },
  89. required: {
  90. type: Boolean,
  91. default: undefined
  92. },
  93. validateFirst: {
  94. type: Boolean,
  95. default: undefined
  96. },
  97. validateStatus: _vueTypes.default.oneOf((0, _type.tuple)('', 'success', 'warning', 'error', 'validating')),
  98. validateTrigger: {
  99. type: [String, Array]
  100. },
  101. messageVariables: {
  102. type: Object
  103. },
  104. hidden: Boolean,
  105. noStyle: Boolean
  106. };
  107. };
  108. exports.formItemProps = formItemProps;
  109. var indexGuid = 0;
  110. // default form item id prefix.
  111. var defaultItemNamePrefixCls = 'form_item';
  112. var _default2 = (0, _vue.defineComponent)({
  113. compatConfig: {
  114. MODE: 3
  115. },
  116. name: 'AFormItem',
  117. inheritAttrs: false,
  118. __ANT_NEW_FORM_ITEM: true,
  119. props: formItemProps(),
  120. slots: ['help', 'label', 'extra'],
  121. setup: function setup(props, _ref) {
  122. var slots = _ref.slots,
  123. attrs = _ref.attrs,
  124. expose = _ref.expose;
  125. (0, _warning.warning)(props.prop === undefined, "`prop` is deprecated. Please use `name` instead.");
  126. var eventKey = "form-item-".concat(++indexGuid);
  127. var _useConfigInject = (0, _useConfigInject2.default)('form', props),
  128. prefixCls = _useConfigInject.prefixCls;
  129. var formContext = (0, _context.useInjectForm)();
  130. var fieldName = (0, _vue.computed)(function () {
  131. return props.name || props.prop;
  132. });
  133. var errors = (0, _vue.ref)([]);
  134. var validateDisabled = (0, _vue.ref)(false);
  135. var inputRef = (0, _vue.ref)();
  136. var namePath = (0, _vue.computed)(function () {
  137. var val = fieldName.value;
  138. return (0, _valueUtil.getNamePath)(val);
  139. });
  140. var fieldId = (0, _vue.computed)(function () {
  141. if (!namePath.value.length) {
  142. return undefined;
  143. } else {
  144. var formName = formContext.name.value;
  145. var mergedId = namePath.value.join('_');
  146. return formName ? "".concat(formName, "_").concat(mergedId) : "".concat(defaultItemNamePrefixCls, "_").concat(mergedId);
  147. }
  148. });
  149. var getNewFieldValue = function getNewFieldValue() {
  150. var model = formContext.model.value;
  151. if (!model || !fieldName.value) {
  152. return;
  153. } else {
  154. return getPropByPath(model, namePath.value, true).v;
  155. }
  156. };
  157. var fieldValue = (0, _vue.computed)(function () {
  158. return getNewFieldValue();
  159. });
  160. var initialValue = (0, _vue.ref)((0, _cloneDeep.default)(fieldValue.value));
  161. var mergedValidateTrigger = (0, _vue.computed)(function () {
  162. var validateTrigger = props.validateTrigger !== undefined ? props.validateTrigger : formContext.validateTrigger.value;
  163. validateTrigger = validateTrigger === undefined ? 'change' : validateTrigger;
  164. return (0, _typeUtil.toArray)(validateTrigger);
  165. });
  166. var rulesRef = (0, _vue.computed)(function () {
  167. var formRules = formContext.rules.value;
  168. var selfRules = props.rules;
  169. var requiredRule = props.required !== undefined ? {
  170. required: !!props.required,
  171. trigger: mergedValidateTrigger.value
  172. } : [];
  173. var prop = getPropByPath(formRules, namePath.value);
  174. formRules = formRules ? prop.o[prop.k] || prop.v : [];
  175. var rules = [].concat(selfRules || formRules || []);
  176. if ((0, _find.default)(rules, function (rule) {
  177. return rule.required;
  178. })) {
  179. return rules;
  180. } else {
  181. return rules.concat(requiredRule);
  182. }
  183. });
  184. var isRequired = (0, _vue.computed)(function () {
  185. var rules = rulesRef.value;
  186. var isRequired = false;
  187. if (rules && rules.length) {
  188. rules.every(function (rule) {
  189. if (rule.required) {
  190. isRequired = true;
  191. return false;
  192. }
  193. return true;
  194. });
  195. }
  196. return isRequired || props.required;
  197. });
  198. var validateState = (0, _vue.ref)();
  199. (0, _vue.watchEffect)(function () {
  200. validateState.value = props.validateStatus;
  201. });
  202. var messageVariables = (0, _vue.computed)(function () {
  203. var variables = {};
  204. if (typeof props.label === 'string') {
  205. variables.label = props.label;
  206. } else if (props.name) {
  207. variables.label = String(name);
  208. }
  209. if (props.messageVariables) {
  210. variables = (0, _objectSpread2.default)((0, _objectSpread2.default)({}, variables), props.messageVariables);
  211. }
  212. return variables;
  213. });
  214. var validateRules = function validateRules(options) {
  215. // no name, no value, so the validate result is incorrect
  216. if (namePath.value.length === 0) {
  217. return;
  218. }
  219. var _props$validateFirst = props.validateFirst,
  220. validateFirst = _props$validateFirst === void 0 ? false : _props$validateFirst;
  221. var _ref2 = options || {},
  222. triggerName = _ref2.triggerName;
  223. var filteredRules = rulesRef.value;
  224. if (triggerName) {
  225. filteredRules = filteredRules.filter(function (rule) {
  226. var trigger = rule.trigger;
  227. if (!trigger && !mergedValidateTrigger.value.length) {
  228. return true;
  229. }
  230. var triggerList = (0, _typeUtil.toArray)(trigger || mergedValidateTrigger.value);
  231. return triggerList.includes(triggerName);
  232. });
  233. }
  234. if (!filteredRules.length) {
  235. return Promise.resolve();
  236. }
  237. var promise = (0, _validateUtil.validateRules)(namePath.value, fieldValue.value, filteredRules, (0, _objectSpread2.default)({
  238. validateMessages: formContext.validateMessages.value
  239. }, options), validateFirst, messageVariables.value);
  240. validateState.value = 'validating';
  241. errors.value = [];
  242. promise.catch(function (e) {
  243. return e;
  244. }).then(function () {
  245. var results = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
  246. if (validateState.value === 'validating') {
  247. var res = results.filter(function (result) {
  248. return result && result.errors.length;
  249. });
  250. validateState.value = res.length ? 'error' : 'success';
  251. errors.value = res.map(function (r) {
  252. return r.errors;
  253. });
  254. formContext.onValidate(fieldName.value, !errors.value.length, errors.value.length ? (0, _vue.toRaw)(errors.value[0]) : null);
  255. }
  256. });
  257. return promise;
  258. };
  259. var _onFieldBlur = function onFieldBlur() {
  260. validateRules({
  261. triggerName: 'blur'
  262. });
  263. };
  264. var _onFieldChange = function onFieldChange() {
  265. if (validateDisabled.value) {
  266. validateDisabled.value = false;
  267. return;
  268. }
  269. validateRules({
  270. triggerName: 'change'
  271. });
  272. };
  273. var clearValidate = function clearValidate() {
  274. validateState.value = props.validateStatus;
  275. validateDisabled.value = false;
  276. errors.value = [];
  277. };
  278. var resetField = function resetField() {
  279. validateState.value = props.validateStatus;
  280. validateDisabled.value = true;
  281. errors.value = [];
  282. var model = formContext.model.value || {};
  283. var value = fieldValue.value;
  284. var prop = getPropByPath(model, namePath.value, true);
  285. if (Array.isArray(value)) {
  286. prop.o[prop.k] = [].concat(initialValue.value);
  287. } else {
  288. prop.o[prop.k] = initialValue.value;
  289. }
  290. // reset validateDisabled after onFieldChange triggered
  291. (0, _vue.nextTick)(function () {
  292. validateDisabled.value = false;
  293. });
  294. };
  295. var htmlFor = (0, _vue.computed)(function () {
  296. return props.htmlFor === undefined ? fieldId.value : props.htmlFor;
  297. });
  298. var onLabelClick = function onLabelClick() {
  299. var id = htmlFor.value;
  300. if (!id || !inputRef.value) {
  301. return;
  302. }
  303. var control = inputRef.value.$el.querySelector("[id=\"".concat(id, "\"]"));
  304. if (control && control.focus) {
  305. control.focus();
  306. }
  307. };
  308. expose({
  309. onFieldBlur: _onFieldBlur,
  310. onFieldChange: _onFieldChange,
  311. clearValidate: clearValidate,
  312. resetField: resetField
  313. });
  314. (0, _FormItemContext.useProvideFormItemContext)({
  315. id: fieldId,
  316. onFieldBlur: function onFieldBlur() {
  317. if (props.autoLink) {
  318. _onFieldBlur();
  319. }
  320. },
  321. onFieldChange: function onFieldChange() {
  322. if (props.autoLink) {
  323. _onFieldChange();
  324. }
  325. },
  326. clearValidate: clearValidate
  327. }, (0, _vue.computed)(function () {
  328. return !!(props.autoLink && formContext.model.value && fieldName.value);
  329. }));
  330. var registered = false;
  331. (0, _vue.watch)(fieldName, function (val) {
  332. if (val) {
  333. if (!registered) {
  334. registered = true;
  335. formContext.addField(eventKey, {
  336. fieldValue: fieldValue,
  337. fieldId: fieldId,
  338. fieldName: fieldName,
  339. resetField: resetField,
  340. clearValidate: clearValidate,
  341. namePath: namePath,
  342. validateRules: validateRules,
  343. rules: rulesRef
  344. });
  345. }
  346. } else {
  347. registered = false;
  348. formContext.removeField(eventKey);
  349. }
  350. }, {
  351. immediate: true
  352. });
  353. (0, _vue.onBeforeUnmount)(function () {
  354. formContext.removeField(eventKey);
  355. });
  356. var debounceErrors = (0, _useDebounce.default)(errors);
  357. var mergedValidateStatus = (0, _vue.computed)(function () {
  358. if (props.validateStatus !== undefined) {
  359. return props.validateStatus;
  360. } else if (debounceErrors.value.length) {
  361. return 'error';
  362. }
  363. return validateState.value;
  364. });
  365. var itemClassName = (0, _vue.computed)(function () {
  366. var _ref3;
  367. return _ref3 = {}, (0, _defineProperty2.default)(_ref3, "".concat(prefixCls.value, "-item"), true), (0, _defineProperty2.default)(_ref3, "".concat(prefixCls.value, "-item-has-feedback"), mergedValidateStatus.value && props.hasFeedback), (0, _defineProperty2.default)(_ref3, "".concat(prefixCls.value, "-item-has-success"), mergedValidateStatus.value === 'success'), (0, _defineProperty2.default)(_ref3, "".concat(prefixCls.value, "-item-has-warning"), mergedValidateStatus.value === 'warning'), (0, _defineProperty2.default)(_ref3, "".concat(prefixCls.value, "-item-has-error"), mergedValidateStatus.value === 'error'), (0, _defineProperty2.default)(_ref3, "".concat(prefixCls.value, "-item-is-validating"), mergedValidateStatus.value === 'validating'), (0, _defineProperty2.default)(_ref3, "".concat(prefixCls.value, "-item-hidden"), props.hidden), _ref3;
  368. });
  369. return function () {
  370. var _slots$default, _props$help;
  371. if (props.noStyle) return (_slots$default = slots.default) === null || _slots$default === void 0 ? void 0 : _slots$default.call(slots);
  372. var help = (_props$help = props.help) !== null && _props$help !== void 0 ? _props$help : slots.help ? (0, _propsUtil.filterEmpty)(slots.help()) : null;
  373. return (0, _vue.createVNode)(_Row.default, (0, _objectSpread2.default)((0, _objectSpread2.default)({}, attrs), {}, {
  374. "class": [itemClassName.value, help !== undefined && help !== null || debounceErrors.value.length ? "".concat(prefixCls.value, "-item-with-help") : '', attrs.class],
  375. "key": "row"
  376. }), {
  377. default: function _default() {
  378. var _props$label, _slots$label, _props$extra, _slots$extra;
  379. return (0, _vue.createVNode)(_vue.Fragment, null, [(0, _vue.createVNode)(_FormItemLabel.default, (0, _objectSpread2.default)((0, _objectSpread2.default)({}, props), {}, {
  380. "htmlFor": htmlFor.value,
  381. "required": isRequired.value,
  382. "requiredMark": formContext.requiredMark.value,
  383. "prefixCls": prefixCls.value,
  384. "onClick": onLabelClick,
  385. "label": (_props$label = props.label) !== null && _props$label !== void 0 ? _props$label : (_slots$label = slots.label) === null || _slots$label === void 0 ? void 0 : _slots$label.call(slots)
  386. }), null), (0, _vue.createVNode)(_FormItemInput.default, (0, _objectSpread2.default)((0, _objectSpread2.default)({}, props), {}, {
  387. "errors": help !== undefined && help !== null ? (0, _typeUtil.toArray)(help) : debounceErrors.value,
  388. "prefixCls": prefixCls.value,
  389. "status": mergedValidateStatus.value,
  390. "ref": inputRef,
  391. "help": help,
  392. "extra": (_props$extra = props.extra) !== null && _props$extra !== void 0 ? _props$extra : (_slots$extra = slots.extra) === null || _slots$extra === void 0 ? void 0 : _slots$extra.call(slots)
  393. }), {
  394. default: slots.default
  395. })]);
  396. }
  397. });
  398. };
  399. }
  400. });
  401. exports.default = _default2;