form.js 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690
  1. import { __assign, __awaiter, __extends, __generator } from "tslib";
  2. import AsyncValidator from 'async-validator';
  3. var EventEmitter = /** @class */ (function () {
  4. function EventEmitter() {
  5. this.listenders = {};
  6. }
  7. EventEmitter.prototype.on = function (event, listener) {
  8. this.listenders[event] = this.listenders[event] || [];
  9. this.listenders[event].push(listener);
  10. return this;
  11. };
  12. EventEmitter.prototype.emit = function (event) {
  13. var args = [];
  14. for (var _i = 1; _i < arguments.length; _i++) {
  15. args[_i - 1] = arguments[_i];
  16. }
  17. var arr = this.listenders[event];
  18. if (arr) {
  19. arr.forEach(function (listener) { return listener.apply(void 0, args); });
  20. }
  21. };
  22. return EventEmitter;
  23. }());
  24. var Field = /** @class */ (function (_super) {
  25. __extends(Field, _super);
  26. /**
  27. * Field构建
  28. * @param ref field ref对象
  29. * @param initialValue 初始值
  30. */
  31. function Field(ref, name, initialValues, rules, validateMessages, required, label, message, validateTrigger) {
  32. var _this = _super.call(this) || this;
  33. _this.ref = ref;
  34. _this.create(name, initialValues[name], rules[name], validateMessages, required, label, message, validateTrigger);
  35. _this.ref.on(function (trigger, value) {
  36. if (trigger === 'onChange') {
  37. _this.setValue(value);
  38. _this.touched = true;
  39. _this.emit('valueChange', value);
  40. }
  41. else if (trigger === 'didUnmount') {
  42. _this.emit('didUnmount');
  43. }
  44. else if (trigger === 'deriveDataFromProps') {
  45. var props = _this.ref.getProps();
  46. if ((value.name && value.name !== props.name) ||
  47. value.required !== props.required ||
  48. value.label !== props.label ||
  49. value.message !== props.message ||
  50. value.validateTrigger !== props.validateTrigger) {
  51. _this.create(value.name, initialValues[value.name], rules[value.name], validateMessages, value.required, value.message, value.label, value.validateTrigger, true);
  52. }
  53. if (value.name !== props.name) {
  54. _this.emit('replaceName', value.name);
  55. }
  56. }
  57. _this.validateTrigger.forEach(function (item) {
  58. if (item === trigger) {
  59. _this.validate();
  60. }
  61. });
  62. });
  63. return _this;
  64. }
  65. Field.prototype.create = function (name, initialValue, rule, validateMessages, required, label, message, validateTrigger, update) {
  66. this.name = name;
  67. this.required = this.transformValidatorRules(name, rule, required, label, message, validateMessages);
  68. if (!update) {
  69. this.reset(initialValue);
  70. }
  71. else {
  72. this.ref.setFormData({
  73. required: this.required,
  74. });
  75. }
  76. var validateTriggerList = validateTrigger || 'onChange';
  77. if (!Array.isArray(validateTriggerList)) {
  78. validateTriggerList = [validateTriggerList];
  79. }
  80. this.validateTrigger = validateTriggerList;
  81. };
  82. /**
  83. *
  84. * @param rule 修改 Validator
  85. * @param name
  86. * @param required
  87. * @param message
  88. * @param validateMessages
  89. * @returns
  90. */
  91. Field.prototype.transformValidatorRules = function (name, rule, required, label, message, validateMessages) {
  92. var _a, _b;
  93. var requiredRule = false;
  94. var validator;
  95. if (rule) {
  96. var ruleList = Array.isArray(rule) ? rule : [rule];
  97. var result = ruleList.find(function (item) { return item.required; });
  98. if (result) {
  99. if (message) {
  100. result.message = message;
  101. }
  102. requiredRule = true;
  103. }
  104. else if (required) {
  105. ruleList.push({
  106. required: required,
  107. message: message,
  108. });
  109. requiredRule = true;
  110. }
  111. validator = new AsyncValidator((_a = {},
  112. _a[name] = ruleList,
  113. _a));
  114. }
  115. else if (required) {
  116. validator = new AsyncValidator((_b = {},
  117. _b[name] = {
  118. required: required,
  119. message: message,
  120. },
  121. _b));
  122. requiredRule = true;
  123. }
  124. if (validator) {
  125. var obj_1 = {
  126. label: label,
  127. };
  128. Object.keys(validator.rules).forEach(function (name) {
  129. validator.rules[name].forEach(function (item) {
  130. if (typeof item.len !== 'undefined') {
  131. obj_1['len'] = item.len;
  132. }
  133. if (typeof item.min !== 'undefined') {
  134. obj_1['min'] = item.min;
  135. }
  136. if (typeof item.max !== 'undefined') {
  137. obj_1['max'] = item.max;
  138. }
  139. if (typeof item.pattern !== 'undefined') {
  140. obj_1['pattern'] = item.pattern;
  141. }
  142. });
  143. });
  144. validator.messages(this.transformValidateMessages(validateMessages, obj_1));
  145. }
  146. this.validator = validator;
  147. return requiredRule;
  148. };
  149. Field.prototype.transformValidateMessages = function (validateMessages, obj) {
  150. if (!validateMessages) {
  151. return;
  152. }
  153. function replaceLabel(validateMessages, target) {
  154. Object.keys(validateMessages).forEach(function (item) {
  155. if (typeof validateMessages[item] === 'string') {
  156. target[item] = validateMessages[item].replace('${label}', obj.label || '');
  157. if (typeof obj.len !== 'undefined') {
  158. target[item] = target[item].replace('${len}', obj.len);
  159. }
  160. if (typeof obj.min !== 'undefined') {
  161. target[item] = target[item].replace('${min}', obj.min);
  162. }
  163. if (typeof obj.max !== 'undefined') {
  164. target[item] = target[item].replace('${max}', obj.max);
  165. }
  166. if (typeof obj.pattern !== 'undefined') {
  167. target[item] = target[item].replace('${pattern}', obj.pattern);
  168. }
  169. return;
  170. }
  171. if (typeof validateMessages[item] === 'object') {
  172. var val = (target[item] = {});
  173. replaceLabel(validateMessages[item], val);
  174. return;
  175. }
  176. target[item] = validateMessages[item];
  177. });
  178. }
  179. var messages = {};
  180. replaceLabel(validateMessages, messages);
  181. return messages;
  182. };
  183. /**
  184. * 设置 Field 值
  185. * @param value Field 值
  186. */
  187. Field.prototype.setValue = function (value) {
  188. this.ref.setFormData({
  189. value: value,
  190. });
  191. };
  192. /**
  193. * 得到 Field 值
  194. */
  195. Field.prototype.getValue = function () {
  196. var value = this.ref.getFormData().value;
  197. return value;
  198. };
  199. /**
  200. * 设置 Field 校验器状态
  201. * @param validatorStatue
  202. */
  203. Field.prototype.setValidatorStatus = function (validatorStatue) {
  204. this.ref.setFormData(validatorStatue);
  205. };
  206. /**
  207. * 得到 Field 校验器状态
  208. * @returns
  209. */
  210. Field.prototype.getValidatorStatus = function () {
  211. var _a = this.ref.getFormData(), status = _a.status, errors = _a.errors;
  212. return {
  213. status: status,
  214. errors: errors,
  215. };
  216. };
  217. /**
  218. * 校验 Field
  219. */
  220. Field.prototype.validate = function () {
  221. return __awaiter(this, void 0, void 0, function () {
  222. var validatorStatusSuccess, value, validator, needUpdateStatus_1, err_1, errors, validatorStatus;
  223. var _a;
  224. var _this = this;
  225. return __generator(this, function (_b) {
  226. switch (_b.label) {
  227. case 0:
  228. validatorStatusSuccess = {
  229. status: 'success',
  230. errors: [],
  231. };
  232. value = this.getValue();
  233. if (!this.validator) {
  234. this.setValidatorStatus(validatorStatusSuccess);
  235. return [2 /*return*/, {
  236. validatorStatus: validatorStatusSuccess,
  237. value: value,
  238. }];
  239. }
  240. validator = this.validator;
  241. _b.label = 1;
  242. case 1:
  243. _b.trys.push([1, 3, , 4]);
  244. needUpdateStatus_1 = true;
  245. Promise.resolve().then(function () {
  246. Promise.resolve().then(function () {
  247. if (needUpdateStatus_1) {
  248. _this.setValidatorStatus({
  249. status: 'validating',
  250. errors: [],
  251. });
  252. }
  253. });
  254. });
  255. return [4 /*yield*/, this.validator.validate((_a = {},
  256. _a[this.name] = value,
  257. _a), function () {
  258. needUpdateStatus_1 = false;
  259. })];
  260. case 2:
  261. _b.sent();
  262. if (validator !== this.validator) {
  263. return [2 /*return*/];
  264. }
  265. this.setValidatorStatus(validatorStatusSuccess);
  266. return [2 /*return*/, {
  267. validatorStatus: validatorStatusSuccess,
  268. value: value,
  269. }];
  270. case 3:
  271. err_1 = _b.sent();
  272. if (validator !== this.validator) {
  273. return [2 /*return*/];
  274. }
  275. errors = err_1.errors;
  276. validatorStatus = {
  277. status: 'error',
  278. errors: errors.map(function (_a) {
  279. var _b = _a.message, message = _b === void 0 ? '' : _b;
  280. return message;
  281. }),
  282. };
  283. this.setValidatorStatus(validatorStatus);
  284. return [2 /*return*/, {
  285. validatorStatus: validatorStatus,
  286. value: value,
  287. }];
  288. case 4: return [2 /*return*/];
  289. }
  290. });
  291. });
  292. };
  293. /**
  294. * 重置 Field
  295. * @param initialValue
  296. */
  297. Field.prototype.reset = function (initialValue) {
  298. this.touched = false;
  299. this.ref.setFormData({
  300. value: initialValue,
  301. required: this.required,
  302. status: 'default',
  303. errors: [],
  304. });
  305. };
  306. /**
  307. * Field 是否被操作
  308. */
  309. Field.prototype.isTouched = function () {
  310. return this.touched;
  311. };
  312. return Field;
  313. }(EventEmitter));
  314. var Form = /** @class */ (function () {
  315. /**
  316. * Form构建
  317. * @param formConfig 表单配置项
  318. */
  319. function Form(formConfig) {
  320. if (formConfig === void 0) { formConfig = {}; }
  321. /**
  322. * 表单ref组件对象
  323. */
  324. this.fields = {};
  325. /**
  326. * 表单字段 change侦听
  327. */
  328. this.changeListeners = [];
  329. /**
  330. * 依赖表
  331. */
  332. this.dependenciesMap = {};
  333. var component2 = my.canIUse('component2');
  334. if (!component2) {
  335. throw new Error('需要使用component2');
  336. }
  337. this.setInitialValues(formConfig.initialValues || {});
  338. this.setRules(formConfig.rules || {});
  339. this.validateMessages = formConfig.validateMessages;
  340. }
  341. /**
  342. * 用户传入的rules转换成async-validator rules
  343. * @param rules 校验规则
  344. */
  345. Form.prototype.transformRules = function (rules) {
  346. var _this = this;
  347. var result = {};
  348. Object.keys(rules).forEach(function (name) {
  349. var rule = rules[name];
  350. var list = (result[name] = []);
  351. var arr = Array.isArray(rule) ? rule : [rule];
  352. arr.forEach(function (item) {
  353. if (typeof item === 'function') {
  354. list.push(item(_this).validator);
  355. }
  356. else {
  357. list.push(__assign({}, item));
  358. }
  359. });
  360. });
  361. return result;
  362. };
  363. /**
  364. * 遍历表单field对象
  365. * @param callback
  366. */
  367. Form.prototype.eachField = function (callback) {
  368. var fields = this.fields;
  369. Object.keys(fields).forEach(function (name) {
  370. var field = fields[name];
  371. callback(field, name);
  372. });
  373. };
  374. /**
  375. * 设置 rules
  376. * @param rules
  377. */
  378. Form.prototype.setRules = function (rules) {
  379. this.rules = this.transformRules(rules);
  380. };
  381. /**
  382. * 添加表单对象
  383. * @param ref 表单ref对象
  384. */
  385. Form.prototype.addItem = function (ref, customName) {
  386. var _this = this;
  387. var props = ref.getProps();
  388. var name = customName || props.name;
  389. if (!name) {
  390. ref.on(function (trigger, value) {
  391. if (trigger === 'deriveDataFromProps') {
  392. if (value.name) {
  393. _this.addItem(ref, value.name);
  394. }
  395. }
  396. });
  397. return;
  398. }
  399. if (this.fields[name]) {
  400. throw new Error("Form \"addItem\" same name: \"".concat(name, "\""));
  401. }
  402. var field = new Field(ref, name, this.initialValues, this.rules, this.validateMessages, props.required, props.label, props.message, props.validateTrigger);
  403. if (props.dependencies) {
  404. props.dependencies.forEach(function (item) {
  405. _this.dependenciesMap[item] = _this.dependenciesMap[item] || [];
  406. if (_this.dependenciesMap[item].indexOf(name) < 0) {
  407. _this.dependenciesMap[item].push(name);
  408. }
  409. });
  410. }
  411. field
  412. .on('valueChange', function (value) {
  413. if (name) {
  414. var arr = _this.dependenciesMap[name];
  415. if (arr) {
  416. arr.forEach(function (item) {
  417. if (_this.fields[item]) {
  418. _this.fields[item].validate();
  419. }
  420. });
  421. }
  422. _this.changeListeners.forEach(function (item) {
  423. var _a;
  424. return item((_a = {},
  425. _a[name] = value,
  426. _a), _this.getFieldsValue());
  427. });
  428. }
  429. })
  430. .on('didUnmount', function () {
  431. delete _this.fields[name];
  432. })
  433. .on('replaceName', function (newName) {
  434. if (!newName) {
  435. delete _this.fields[name];
  436. return;
  437. }
  438. if (_this.fields[newName]) {
  439. throw new Error("Form \"addItem\" same name: \"".concat(newName, "\""));
  440. }
  441. _this.fields[newName] = field;
  442. delete _this.fields[name];
  443. name = newName;
  444. });
  445. if (name) {
  446. this.fields[name] = field;
  447. }
  448. };
  449. /**
  450. * 设置表单值
  451. * @param name 表单名称
  452. * @param value 表单初始值
  453. */
  454. Form.prototype.setFieldValue = function (name, value) {
  455. var field = this.fields[name];
  456. if (field) {
  457. field.setValue(value);
  458. field.setValidatorStatus({
  459. status: 'success',
  460. errors: [],
  461. });
  462. }
  463. };
  464. /**
  465. * 设置表单值
  466. * @param name 表单名称
  467. * @param value 表单初始值
  468. */
  469. Form.prototype.setFieldsValue = function (values) {
  470. var _this = this;
  471. Object.keys(values).forEach(function (name) {
  472. _this.setFieldValue(name, values[name]);
  473. });
  474. };
  475. /**
  476. * 设置 initialValues,这个操作不会对页面进行修改,要是需要重置表单可跟上 reset 方法;
  477. * 这样是对于表单已经在编辑,但是需要重新initialValues的场景
  478. *
  479. * eg:
  480. * this.setInitialValues(initialValues);
  481. * this.reset();
  482. *
  483. * @param initialValues
  484. */
  485. Form.prototype.setInitialValues = function (initialValues) {
  486. this.initialValues = initialValues;
  487. };
  488. /**
  489. * 获取对应字段名的值
  490. * @param name
  491. * @returns
  492. */
  493. Form.prototype.getFieldValue = function (name) {
  494. var field = this.fields[name];
  495. if (!field) {
  496. return;
  497. }
  498. return field.getValue();
  499. };
  500. /**
  501. * 获取一组字段名对应的值
  502. * @param nameList
  503. * @returns
  504. */
  505. Form.prototype.getFieldsValue = function (nameList) {
  506. var _this = this;
  507. var fieldsValue = {};
  508. nameList = nameList || Object.keys(this.fields);
  509. nameList.forEach(function (name) {
  510. fieldsValue[name] = _this.getFieldValue(name);
  511. });
  512. return fieldsValue;
  513. };
  514. /**
  515. * 获取对应字段名的校验器状态
  516. * @param name
  517. * @returns
  518. */
  519. Form.prototype.getFieldValidatorStatus = function (name) {
  520. var field = this.fields[name];
  521. if (!field) {
  522. return;
  523. }
  524. return field.getValidatorStatus();
  525. };
  526. /**
  527. * 获取一组字段名的校验器状态
  528. * @param nameList
  529. * @returns
  530. */
  531. Form.prototype.getFieldsValidatorStatus = function (nameList) {
  532. var _this = this;
  533. var fieldsValidatorStatus = {};
  534. nameList = nameList || Object.keys(this.fields);
  535. nameList.forEach(function (name) {
  536. fieldsValidatorStatus[name] = _this.getFieldValidatorStatus(name);
  537. });
  538. return fieldsValidatorStatus;
  539. };
  540. /**
  541. * 设置对应字段名的校验器状态
  542. * @param name 表单名称
  543. * @param validatorStatus 校验状态
  544. * @returns
  545. */
  546. Form.prototype.setFieldValidatorStatus = function (name, validatorStatus) {
  547. var field = this.fields[name];
  548. if (!field) {
  549. return;
  550. }
  551. return field.setValidatorStatus(validatorStatus);
  552. };
  553. /**
  554. * 设置一组字段名的校验器状态
  555. * @param fieldsValidatorStatus 表单校验状态
  556. * @returns
  557. */
  558. Form.prototype.setFieldsValidatorStatus = function (fieldsValidatorStatus) {
  559. var _this = this;
  560. Object.keys(fieldsValidatorStatus).forEach(function (name) {
  561. _this.setFieldValidatorStatus(name, fieldsValidatorStatus[name]);
  562. });
  563. };
  564. /**
  565. * 检查对应字段是否被用户操作过
  566. * @param name 字段名称
  567. * @returns
  568. */
  569. Form.prototype.isFieldTouched = function (name) {
  570. var field = this.fields[name];
  571. if (!field) {
  572. return false;
  573. }
  574. return field.isTouched();
  575. };
  576. /**
  577. * 指定表单字段值更新时触发回调方法
  578. * @param name 表单字段名称
  579. * @param callback 回调方法
  580. */
  581. Form.prototype.onValueChange = function (name, callback) {
  582. this.changeListeners.push(function (changedValues, allValues) {
  583. if (name in changedValues) {
  584. callback(changedValues[name], allValues);
  585. }
  586. });
  587. };
  588. /**
  589. * 表单字段值更新时触发回调方法
  590. * @param name 表单字段名称
  591. * @param callback 回调方法
  592. */
  593. Form.prototype.onValuesChange = function (callback) {
  594. this.changeListeners.push(function (changedValues, allValues) {
  595. callback(changedValues, allValues);
  596. });
  597. };
  598. /**
  599. * 表单提交
  600. */
  601. Form.prototype.submit = function () {
  602. return __awaiter(this, void 0, void 0, function () {
  603. var values, arr, result, errorFields;
  604. var _this = this;
  605. return __generator(this, function (_a) {
  606. switch (_a.label) {
  607. case 0:
  608. values = {};
  609. arr = [];
  610. this.eachField(function (field, name) {
  611. arr.push((function () { return __awaiter(_this, void 0, void 0, function () {
  612. var _a;
  613. return __generator(this, function (_b) {
  614. switch (_b.label) {
  615. case 0:
  616. _a = [{}];
  617. return [4 /*yield*/, field.validate()];
  618. case 1: return [2 /*return*/, __assign.apply(void 0, [__assign.apply(void 0, _a.concat([(_b.sent())])), { name: name }])];
  619. }
  620. });
  621. }); })());
  622. });
  623. return [4 /*yield*/, Promise.all(arr)];
  624. case 1:
  625. result = _a.sent();
  626. errorFields = [];
  627. result.forEach(function (obj) {
  628. if (!obj) {
  629. return;
  630. }
  631. var name = obj.name, value = obj.value, validatorStatus = obj.validatorStatus;
  632. if (validatorStatus.status === 'error') {
  633. errorFields.push({
  634. name: name,
  635. errors: validatorStatus.errors,
  636. });
  637. }
  638. values[name] = value;
  639. });
  640. if (errorFields.length > 0) {
  641. throw {
  642. values: values,
  643. errorFields: errorFields,
  644. };
  645. }
  646. return [2 /*return*/, values];
  647. }
  648. });
  649. });
  650. };
  651. /**
  652. * 表单重置
  653. */
  654. Form.prototype.reset = function () {
  655. var _this = this;
  656. this.eachField(function (field, name) {
  657. var initialValue = _this.initialValues[name];
  658. field.reset(initialValue);
  659. });
  660. };
  661. return Form;
  662. }());
  663. export { Form };
  664. export function createForm(_a) {
  665. var _b = _a === void 0 ? {} : _a, _c = _b.methods, methods = _c === void 0 ? {} : _c;
  666. return {
  667. data: {
  668. formData: {
  669. value: undefined,
  670. status: 'default',
  671. errors: [],
  672. },
  673. },
  674. didUnmount: function () {
  675. this.emit('didUnmount');
  676. },
  677. deriveDataFromProps: function (nextProps) {
  678. this.emit('deriveDataFromProps', nextProps);
  679. },
  680. methods: __assign({ emit: function (trigger, value) { }, setFormData: function (values) {
  681. this.setData(__assign(__assign({}, this.data), { formData: __assign(__assign({}, this.data.formData), values) }));
  682. }, getFormData: function () {
  683. return this.data.formData;
  684. }, on: function (callback) {
  685. this.emit = callback;
  686. }, getProps: function () {
  687. return this.props;
  688. } }, methods),
  689. };
  690. }