form.stories.tsx 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  1. import React, { FunctionComponent } from 'react';
  2. import { storiesOf } from '@storybook/react';
  3. import { Form, useFormState, useFormApi, withField, Input, Button, Upload, withFormApi, withFormState } from '../../index';
  4. const stories = storiesOf('Form', module);
  5. import { FormApiContext } from '../context';
  6. import type { FormApi, FormFCChild, FormState } from '../interface';
  7. const treeData = [
  8. {
  9. label: '浙江省',
  10. value: 'zhejiang',
  11. key: '0',
  12. children: [
  13. {
  14. label: '杭州市',
  15. value: 'hangzhou',
  16. key: '0-0',
  17. children: [
  18. {
  19. label: '西湖区',
  20. value: 'xihu',
  21. key: '0-0-0',
  22. },
  23. {
  24. label: '萧山区',
  25. value: 'xiaoshan',
  26. key: '0-0-1',
  27. },
  28. {
  29. label: '临安区',
  30. value: 'linan',
  31. key: '0-0-2',
  32. },
  33. ],
  34. },
  35. {
  36. label: '宁波市',
  37. value: 'ningbo',
  38. key: '0-1',
  39. children: [
  40. {
  41. label: '海曙区',
  42. value: 'haishu',
  43. key: '0-1-0',
  44. },
  45. {
  46. label: '江北区',
  47. value: 'jiangbei',
  48. key: '0-1-1',
  49. },
  50. ],
  51. },
  52. ],
  53. },
  54. ];
  55. const htmlInput = (props: any) => {
  56. let value = props.value || '';
  57. delete props.validateStatus; // prevent props being transparently transmitted to DOM
  58. return <input {...props} value={value} />;
  59. };
  60. const FieldB = withField(Input);
  61. const FieldA = withField(htmlInput, { valueKey: 'value', onKeyChangeFnName: 'onChange', valuePath: 'target.value' });
  62. const Fields: FunctionComponent<FormFCChild> = ({ formState, values, formApi }) => {
  63. const ref = React.useRef();
  64. return (
  65. <>
  66. <Form.Rating field='test' className='fe' count={2} ref={ref} />
  67. <Form.Input field='test' ref={ref} />
  68. <Input size='default' showClear insetLabel />
  69. <FieldB insetLabel placeholder='fe' fieldClassName='fefe' field='custom' />
  70. {/* <Button onClick={() => formApi.setValue('fieldA', 'fe')}>set</Button> */}
  71. <Form.Select field='test' ref={ref}>
  72. <Form.Select.Option value="f1"></Form.Select.Option>
  73. <Form.Select.Option value="f2"></Form.Select.Option>
  74. </Form.Select>
  75. <Form.Input field="UserName" label="用户名" ref={ref} />
  76. <Form.TextArea field="textarea" onKeyDown={(v: any) => console.log(v)} ref={ref} />
  77. <Form.Input field="Password" label="密码" />
  78. <Form.InputNumber field="number" ref={ref} />
  79. <Form.Rating field="rating" />
  80. <Form.Switch field="switch" checkedText="on" uncheckedText="off" ref={ref} />
  81. <Form.Cascader
  82. placeholder="请选择所在地区"
  83. field="area"
  84. ref={ref}
  85. label={{ text: '123', required: true, extra: 123 }}
  86. treeData={treeData}
  87. ></Form.Cascader>
  88. <Form.TimePicker field="time" minuteStep={2} ref={ref} />
  89. <Form.AutoComplete field="fe" />
  90. <Form.TreeSelect field="treeSelect" treeData={treeData} ref={ref} />
  91. <Form.Slider field="slider" ref={ref} />
  92. <Form.DatePicker field="datepicker" ref={ref} />
  93. <Form.CheckboxGroup
  94. field="type"
  95. ref={ref}
  96. label="申请类型(CheckboxGroup)"
  97. initValue={['user', 'admin']}
  98. rules={[{ required: true }]}
  99. >
  100. <Form.Checkbox value="admin">admin</Form.Checkbox>
  101. <Form.Checkbox value="user">user</Form.Checkbox>
  102. <Form.Checkbox value="guest">guest</Form.Checkbox>
  103. <Form.Checkbox value="root">root</Form.Checkbox>
  104. </Form.CheckboxGroup>
  105. <Form.RadioGroup
  106. field="radio"
  107. ref={ref}
  108. label="是否独占资源(Radio)"
  109. rules={[{ type: 'boolean' }, { required: true, message: '必须选择是否独占 ' }]}
  110. >
  111. <Form.Radio value={1}>是</Form.Radio>
  112. <Form.Radio value={0}>否</Form.Radio>
  113. </Form.RadioGroup>
  114. <Form.Checkbox field='abc' noLabel>
  115. 我已阅读并清楚相关规定(Checkbox)
  116. </Form.Checkbox>
  117. <Form.Label text="fe" required />
  118. <Form.ErrorMessage error="errorText" />
  119. <FieldB field="custom" />
  120. <FieldA field="cuB" />
  121. <Form.TagInput field='tagInput' ref={ref} ></Form.TagInput>
  122. <Form.Upload ref={ref} fileName='semi' action='https://test.com' field='file' />
  123. <Form.Slot />
  124. <code style={{ marginTop: 30 }}>{JSON.stringify(formState)}</code>
  125. </>
  126. )
  127. };
  128. stories.add('Form', () => <Form>{Fields}</Form>);
  129. interface IProps {
  130. [x:string]: any;
  131. }
  132. interface IState {
  133. visible: boolean;
  134. }
  135. interface FData {
  136. test: boolean;
  137. test2: boolean;
  138. test3: string;
  139. test4: {
  140. event: string,
  141. },
  142. test5: {
  143. kkk: {
  144. jjj: number
  145. }
  146. }
  147. testK: boolean;
  148. // [x: string]: any;
  149. }
  150. class Demo extends React.Component<IProps, IState> {
  151. formApi: FormApi<FData>
  152. constructor(props:any) {
  153. super(props);
  154. this.state = { visible: false};
  155. this.asyncValidateFields = this.asyncValidateFields.bind(this);
  156. }
  157. getFormApi(formApi) {
  158. this.formApi = formApi;
  159. }
  160. setData() {
  161. const formApi = this.formApi;
  162. // set
  163. formApi.setValue('test3', 123);
  164. formApi.setValue('test4.event', 123);
  165. formApi.setValue('test5.kkk', 123);
  166. formApi.setValue('test5.kkk.jjj', 123);
  167. formApi.setValue('keyNotExist', 123);
  168. formApi.setValue('test4.notExist', 123);
  169. formApi.setValue('test5.kkk.notExist', 123);
  170. // get
  171. let test3 = formApi.getValue('test3');
  172. let test4 = formApi.getValue('test4');
  173. let test4event = formApi.getValue('test4.event');
  174. let test5kkk = formApi.getValue('test5.kkk');
  175. let test5kkkjjj = formApi.getValue('test5.kkk.jjj');
  176. let a = formApi.getValue('keyNotExist');
  177. let b = formApi.getValue('test5.kkk.notExist');
  178. let c = formApi.getValue('test4.notExist');
  179. }
  180. asyncValidateFields(values) {
  181. const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));
  182. return sleep(2000).then(() => {
  183. let errors = {} as Record<string, any>;
  184. if (values.name !== 'mike') {
  185. errors.name = 'you must name mike';
  186. }
  187. if (values.sex !== 'female') {
  188. errors.sex = 'sex not valid';
  189. }
  190. return errors;
  191. });
  192. }
  193. render() {
  194. const { visible } = this.state;
  195. return (
  196. <>
  197. <Form<FData>
  198. getFormApi={this.getFormApi}
  199. onSubmit={values => console.log(values.test2)}
  200. onChange={formState => formState.values.test}
  201. validateFields={this.asyncValidateFields}
  202. // validateFields={values => ({ test4: 'test4 empty', test2: '', fieldNotExist: 'xx' }) }
  203. >
  204. </Form>
  205. </>
  206. );
  207. }
  208. }
  209. class WithoutGenericsType extends React.Component<IProps, IState> {
  210. formApi: FormApi
  211. constructor(props: any) {
  212. super(props);
  213. }
  214. getFormApi(formApi) {
  215. this.formApi = formApi;
  216. }
  217. setData() {
  218. const formApi = this.formApi;
  219. formApi.setValue('test3', 123);
  220. formApi.setValue('test8', 123);
  221. formApi.setValue('test4.event', 123);
  222. formApi.setValue('test5.kkk', 123);
  223. formApi.setValue('test5.kkk.jjj', 123);
  224. formApi.setValue('test5.kkk.ppp', 123);
  225. formApi.setValue('test4.5', 123);
  226. }
  227. render() {
  228. return (
  229. <>
  230. <Form
  231. getFormApi={this.getFormApi}
  232. onSubmit={values => console.log(values.test2)}
  233. onChange={formState => formState.values.test}
  234. validateFields={values => ({ test4: 'test4 empty', test2: '' })}
  235. >
  236. </Form>
  237. </>
  238. );
  239. }
  240. }
  241. stories.add('Form render', () => <Form render={({values, formApi, formState}) => <div></div>}></Form>);
  242. interface CodeProps {
  243. type?: 'email' | 'phone';
  244. test?: 'a' | 'b' | 'c';
  245. onSend?: () => Promise<void>
  246. }
  247. class CodeC extends React.Component<CodeProps & { formState?: FormState, formApi?: FormApi }, IState> {
  248. state: IState = {
  249. visible: false,
  250. };
  251. render() {
  252. const { formState } = this.props;
  253. return <div>
  254. t
  255. </div>;
  256. }
  257. }
  258. const t = () => (<CodeC type='email'></CodeC>);
  259. const DoubleWrap = withFormState(withFormApi(CodeC));
  260. const OneWrap = withFormApi(CodeC);
  261. stories.add('Form children', () => <Form>
  262. {({ formState, formApi, values }) => (
  263. <>
  264. <Form.Input field='fe'>
  265. </Form.Input>
  266. <DoubleWrap type='email' test='c'></DoubleWrap>
  267. <OneWrap type='email'></OneWrap>
  268. <CodeC type='email'></CodeC>
  269. <Form.DatePicker field='role'/>
  270. </>
  271. )
  272. }
  273. </Form>);