validateDemo.jsx 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491
  1. import React, { useState, useLayoutEffect, Component } from 'react';
  2. import { storiesOf } from '@storybook/react';
  3. import { Button, Modal, TreeSelect, Row, Col, Avatar, Toast, Select as BasicSelect,
  4. Form,
  5. useFormState,
  6. useFormApi,
  7. useFieldApi,
  8. useFieldState,
  9. withFormState,
  10. withFormApi,
  11. withField,
  12. ArrayField,
  13. AutoComplete,
  14. Collapse,
  15. Icon } from '../../../index';
  16. import { ComponentUsingFormState } from '../Hook/hookDemo';
  17. import Textarea from '../../../input/textarea';
  18. const { Input, Select, DatePicker, Switch, Slider, CheckboxGroup, Checkbox, RadioGroup, Radio, TimePicker, InputNumber, InputGroup } = Form;
  19. // Form level validate
  20. class ValidateFieldsDemo extends Component {
  21. constructor() {
  22. super();
  23. this.syncValidate = this.syncValidate.bind(this);
  24. this.asyncValidate = this.asyncValidate.bind(this);
  25. }
  26. syncValidate(values) {
  27. const errors = {};
  28. if (values.name !== 'mike') {
  29. errors.name = 'you must name mike';
  30. }
  31. if (values.sex !== 'female') {
  32. errors.sex = 'must be woman';
  33. // errors.group = {};
  34. // errors.group.sort = '';
  35. }
  36. errors.familyName = [
  37. { before: 'before errror inject success ', after: 'after error inject success' },
  38. 'familyName[1] error inject success'
  39. ];
  40. // // return '';
  41. return errors;
  42. }
  43. asyncValidate(values) {
  44. const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));
  45. return sleep(2000).then(() => {
  46. let errors = {};
  47. if (values.name !== 'mike') {
  48. errors.name = 'you must name mike';
  49. }
  50. if (values.sex !== 'female') {
  51. errors.sex = 'sex not valid';
  52. }
  53. console.log(errors);
  54. return errors;
  55. });
  56. }
  57. render() {
  58. return (
  59. <>
  60. <h4 style={{ marginTop: 400 }}>同步校验</h4>
  61. <Form
  62. autoScrollToError
  63. validateFields={this.syncValidate}
  64. onReset={v => console.log('reset')}
  65. onChange={v => console.log(v)}
  66. onValueChange={v => console.log('onValueChange')}>
  67. <Form.InputGroup label="group" style={{ width: 600 }}>
  68. <Input field="group.name" style={{ width: 280 }} />
  69. <Input field="group.sort" style={{ width: 290 }} />
  70. </Form.InputGroup>
  71. <Input field="name" trigger="blur" />
  72. <Input field="familyName[0].before" trigger="blur" />
  73. <Input field="familyName[0].after" trigger="blur" />
  74. <Input field="familyName[1]" trigger="blur" />
  75. <Input field="sex" trigger="blur" />
  76. <Button type="primary" htmlType="submit">
  77. Submit
  78. </Button>
  79. <Button htmlType="reset">reset</Button>
  80. <ComponentUsingFormState />
  81. </Form>
  82. <h4>异步校验</h4>
  83. <Form
  84. autoScrollToError
  85. validateFields={this.asyncValidate}
  86. onReset={v => console.log('reset')}
  87. onChange={v => console.log(v)}
  88. onValueChange={v => console.log('onValueChange')}>
  89. <Input field="name" trigger="blur" />
  90. <Button type="primary" htmlType="submit">
  91. Submit
  92. </Button>
  93. <Button htmlType="reset">reset</Button>
  94. <ComponentUsingFormState />
  95. </Form>
  96. </>
  97. );
  98. }
  99. }
  100. // Field level
  101. class CustomValidateDemo extends Component {
  102. constructor() {
  103. super();
  104. this.validateName = this.validateName.bind(this);
  105. this.asyncValidate = this.asyncValidate.bind(this);
  106. }
  107. validateName(val) {
  108. if (!val) {
  109. return '【sync】can\'t be empty';
  110. } else if (val.length <= 5) {
  111. return <span>我是传入的reactNode</span>;
  112. // // return '【sync】must more than 5';
  113. }
  114. return;
  115. }
  116. asyncValidate(val, values) {
  117. const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));
  118. return sleep(2000).then(() => {
  119. if (!val) {
  120. return '【async】can\'t be empty';
  121. // throw '【async】can\'t be empty';
  122. } else if (val.length <= 5) {
  123. return '【async】must more than 5';
  124. // throw '【async】must more than 5';
  125. } else {
  126. return;
  127. }
  128. });
  129. }
  130. render() {
  131. return (
  132. <Form autoScrollToError>
  133. <Input field="name" validate={this.asyncValidate} trigger="blur" />
  134. <Input field="familyName" validate={this.validateName} trigger="blur" name="familyName" />
  135. <Input field="code" validate={this.asyncValidate} trigger={['change', 'mount']} />
  136. <Button type="primary" htmlType="submit">
  137. Submit
  138. </Button>
  139. <Button htmlType="reset">reset</Button>
  140. <h5>Component using formState:</h5>
  141. <ComponentUsingFormState />
  142. </Form>
  143. );
  144. }
  145. }
  146. // validate partial fields
  147. // reset partial fields
  148. class PartValidAndResetDemo extends Component {
  149. constructor() {
  150. super();
  151. this.validate = this.validate.bind(this);
  152. this.getFormApi = this.getFormApi.bind(this);
  153. this.validatePartial = this.validatePartial.bind(this);
  154. this.resetPartial = this.resetPartial.bind(this);
  155. }
  156. getFormApi(formApi) {
  157. this.formApi = formApi;
  158. }
  159. validate(val) {
  160. if (!val) {
  161. return '【sync】can\'t be empty';
  162. } else if (val.length <= 5) {
  163. return <span>我是传入的reactNode</span>;
  164. }
  165. return;
  166. }
  167. validatePartial(type) {
  168. let scope = this.formApi.getValue('validateScope');
  169. !scope ? scope = [] : null;
  170. this.formApi.validate(scope)
  171. .then(values => {
  172. console.log(values);
  173. Toast.success('pass');
  174. }).catch(error => {
  175. Toast.error('error');
  176. console.log(error);
  177. });
  178. }
  179. resetPartial() {
  180. let scope = this.formApi.getValue('resetScope');
  181. this.formApi.reset(scope);
  182. }
  183. render() {
  184. let options = ['a', 'b', 'c', 'd', 'b.name'].map(item => ({ label: item, value: item }));
  185. return (
  186. <Form getFormApi={this.getFormApi} autoScrollToError>
  187. <Input field="a[1]" validate={this.validate} trigger="blur" />
  188. <Input field="a[0]" validate={this.validate} trigger="blur" />
  189. <Input field="ackk" validate={this.validate} trigger="blur" />
  190. <Input field="b.name[0]" validate={this.validate} trigger="blur" name="familyName" />
  191. <Input field="b.name[1]" validate={this.validate} trigger="blur" name="familyName" />
  192. <Input field="b.type" validate={this.validate} trigger="blur" name="familyName" />
  193. <Input field="c" validate={this.validate} trigger="change" name="familyName" />
  194. <Input field="d" validate={this.validate} trigger="change" name="familyName" />
  195. <CheckboxGroup options={options} field="validateScope" label="Need Validate Fields" direction="horizontal" />
  196. <CheckboxGroup options={options} field="resetScope" label="Need Reset Fields" direction="horizontal" />
  197. <Button type="primary" htmlType="submit">submit</Button>
  198. <Button htmlType="reset">reset</Button>
  199. <Button onClick={() => this.validatePartial('all')}>all validate</Button>
  200. <Button onClick={() => this.validatePartial()}>partial validate</Button>
  201. <Button onClick={this.resetPartial}>partial reset</Button>
  202. <ComponentUsingFormState />
  203. </Form>
  204. );
  205. }
  206. }
  207. class RulesValidateDemo extends Component {
  208. constructor() {
  209. super();
  210. this.validate = this.validate.bind(this);
  211. this.getFormApi = this.getFormApi.bind(this);
  212. this.set = this.set.bind(this);
  213. }
  214. validate(values) {
  215. this.formApi.validate().then(value => {
  216. Toast.info('reslove');
  217. }).catch(error => {
  218. Toast.error('error');
  219. });
  220. }
  221. getFormApi(formApi) {
  222. this.formApi = formApi;
  223. }
  224. set(val) {
  225. this.formApi.setError('panel[1].a', val);
  226. }
  227. render() {
  228. return (
  229. <>
  230. <Form
  231. layout="horizontal"
  232. getFormApi={this.getFormApi}
  233. autoScrollToError
  234. onReset={v => console.log('reset')}
  235. onChange={v => console.log(v)}
  236. onValueChange={v => console.log('onValueChange')}>
  237. <Input field="panel[0].a" trigger="custom" rules={[{ required: true, message: '字段不能为空' }]} />
  238. <Input field="panel[0].b" trigger="custom" rules={[{ required: true, message: '字段不能为空' }]} />
  239. <Input field="panel[0].c" trigger="custom" rules={[{ required: true, message: '字段不能为空' }]} />
  240. <Input field="panel[1].a" trigger="custom" rules={[{ required: false, message: '字段不能为空' }]} />
  241. <Button type="primary" onClick={this.validate}>
  242. validate
  243. </Button>
  244. <Button htmlType="reset">reset</Button>
  245. <Button onClick={() => this.set('')}>setEmptyString</Button>
  246. <Button onClick={() => this.set(undefined)}>setUndefined</Button>
  247. <ComponentUsingFormState />
  248. </Form>
  249. </>
  250. );
  251. }
  252. }
  253. class SetBugDemo extends Component {
  254. constructor() {
  255. super();
  256. this.state = {
  257. key: 1
  258. };
  259. }
  260. validate = values => {
  261. this.formApi.validate().then(value => {
  262. Toast.info('reslove');
  263. }).catch(error => {
  264. Toast.error('error');
  265. });
  266. }
  267. getFormApi = formApi => {
  268. this.formApi = formApi;
  269. }
  270. set = val => {
  271. this.formApi.setError('panel[1].a', val);
  272. }
  273. refresh = val => {
  274. this.setState({ key: new Date().valueOf() });
  275. }
  276. render() {
  277. const commonRules = [{
  278. required: true, message: '不能为空'
  279. }];
  280. const { key } = this.state;
  281. return (
  282. <>
  283. <Form
  284. key={key}
  285. layout="horizontal"
  286. getFormApi={this.getFormApi}
  287. autoScrollToError
  288. onReset={v => console.log('reset')}
  289. onChange={v => console.log(v)}
  290. onValueChange={v => console.log('onValueChange')}>
  291. {({ formState, values }) => (
  292. <>
  293. <Form.Input field="panels[11].start_time" rules={commonRules} />
  294. <Form.Input field="panels[11].end_time" rules={commonRules} />
  295. <Form.Input field="panels[13].start_time" rules={commonRules} />
  296. <Form.Input field="panels[13].end_time" rules={commonRules} />
  297. <Form.Input field="a.a1" rules={commonRules} />
  298. <Form.Input field="a.a2" rules={commonRules} />
  299. <Textarea style={{ margin: 10 }} value={JSON.stringify(formState.errors)} />
  300. <Textarea style={{ margin: 10 }} value={JSON.stringify(formState.values)} />
  301. {/* <ComponentUsingFormState/> */}
  302. <Button type="primary" onClick={this.validate}>
  303. validate
  304. </Button>
  305. <Button htmlType="reset">reset</Button>
  306. <Button onClick={this.refresh}>refresh</Button>
  307. </>
  308. )}
  309. </Form>
  310. </>
  311. );
  312. }
  313. }
  314. class UnmountedLeafDemo extends React.Component {
  315. constructor() {
  316. super();
  317. this.state = {
  318. show: true,
  319. };
  320. this.change = this.change.bind(this);
  321. }
  322. change() {
  323. let { show } = this;
  324. this.setState({ show: !show });
  325. }
  326. render() {
  327. let { show } = this.state;
  328. return (
  329. <Form style={{ width: 500 }} labelPosition="left" labelWidth="220px" allowEmpty>
  330. {({ values }) => (
  331. <>
  332. {JSON.stringify(values)}
  333. {show ? <Form.Input field="array[0].name" /> : null}
  334. <Button onClick={this.change}>change</Button>
  335. </>
  336. )}
  337. </Form>
  338. );
  339. }
  340. }
  341. class RulesExample extends React.Component {
  342. constructor() {
  343. super();
  344. this.state = {
  345. initValues: {
  346. name: 'semi',
  347. role: 'rd'
  348. }
  349. };
  350. this.getFormApi = this.getFormApi.bind(this);
  351. }
  352. getFormApi(formApi) {
  353. this.formApi = formApi;
  354. }
  355. render() {
  356. const { Select, Input } = Form;
  357. const style = { width: '100%' };
  358. return (
  359. <Form initValues={this.state.initValues}>
  360. <Input
  361. field="name"
  362. label="名称(Input)"
  363. style={style}
  364. trigger="blur"
  365. rules={[
  366. { required: true, message: 'required error' },
  367. { type: 'string', message: 'type error' },
  368. { validator: (rule, value) => value === 'muji', message: 'not muji' }
  369. ]}
  370. />
  371. <Select field="role" style={style} label="角色" placeholder="请选择你的角色" initValue={'pm'}>
  372. <Select.Option value="operate">运营</Select.Option>
  373. <Select.Option value="rd">开发</Select.Option>
  374. <Select.Option value="pm">产品</Select.Option>
  375. <Select.Option value="ued">设计</Select.Option>
  376. </Select>
  377. </Form>
  378. );
  379. }
  380. }
  381. class RaceAsyncDemo extends React.Component {
  382. constructor() {
  383. super();
  384. this.asyncValidate = this.asyncValidate.bind(this);
  385. }
  386. asyncValidate(val, values) {
  387. const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));
  388. let time = 1000;
  389. if (val === 'semi') {
  390. time = 4000;
  391. }
  392. return sleep(time).then(() => {
  393. if (!val) {
  394. return 'can\'t be empty';
  395. } else if (val === 'semi') {
  396. return 'sleep 4000';
  397. } else if (val === 'sem') {
  398. return 'sleep 1000';
  399. } else {
  400. return '';
  401. }
  402. });
  403. }
  404. render() {
  405. return (
  406. <Form>
  407. <Form.Input
  408. field='name'
  409. label='props.rules ract async validate'
  410. // validate={this.asyncValidate}
  411. trigger='blur'
  412. rules={[
  413. {
  414. type: 'string',
  415. asyncValidator: (rule, value) => {
  416. const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));
  417. let time = 1000;
  418. if (value === 'semi') {
  419. time = 4000;
  420. }
  421. return sleep(time).then(() => {
  422. if (value === 'semi') {
  423. throw Error('sleep 4000');
  424. } else if (value === 'sem') {
  425. throw Error('sleep 1000');
  426. } else {
  427. return;
  428. }
  429. });
  430. }
  431. }
  432. ]}
  433. />
  434. <Form.Input
  435. field='nick'
  436. label='props.validate ract async validate'
  437. validate={this.asyncValidate}
  438. trigger='blur'
  439. />
  440. <Button htmlType="reset">reset</Button>
  441. </Form>
  442. );
  443. }
  444. }
  445. export { ValidateFieldsDemo, CustomValidateDemo, PartValidAndResetDemo, RulesValidateDemo, SetBugDemo, UnmountedLeafDemo, RulesExample, RaceAsyncDemo };