UNPKG

16.3 kBMarkdownView Raw
1# rc-field-form
2
3React Performance First Form Component.
4
5[![NPM version][npm-image]][npm-url] [![dumi](https://img.shields.io/badge/docs%20by-dumi-blue?style=flat-square)](https://github.com/umijs/dumi) [![build status][github-actions-image]][github-actions-url] [![Codecov][codecov-image]][codecov-url] [![npm download][download-image]][download-url]
6
7[npm-image]: http://img.shields.io/npm/v/rc-field-form.svg?style=flat-square
8[npm-url]: http://npmjs.org/package/rc-field-form
9[github-actions-image]: https://github.com/react-component/field-form/workflows/CI/badge.svg
10[github-actions-url]: https://github.com/react-component/field-form/actions
11[codecov-image]: https://img.shields.io/codecov/c/github/react-component/field-form/master.svg?style=flat-square
12[codecov-url]: https://codecov.io/gh/react-component/field-form/branch/master
13[download-image]: https://img.shields.io/npm/dm/rc-field-form.svg?style=flat-square
14[download-url]: https://npmjs.org/package/rc-field-form
15
16## Development
17
18```bash
19npm install
20npm start
21open http://localhost:8000
22```
23
24## Feature
25
26- Support react.js and even react-native
27- Validate fields with [async-validator](https://github.com/yiminghe/async-validator/)
28
29## Install
30
31[![rc-field-form](https://nodei.co/npm/rc-field-form.png)](https://npmjs.org/package/rc-field-form)
32
33## Usage
34
35```js | pure
36import Form, { Field } from 'rc-field-form';
37
38const Input = ({ value = "", ...props }) => <input value={value} {...props} />;
39
40const Demo = () => {
41 return (
42 <Form
43 onFinish={(values) => {
44 console.log("Finish:", values);
45 }}
46 >
47 <Field name="username">
48 <Input placeholder="Username" />
49 </Field>
50 <Field name="password">
51 <Input placeholder="Password" />
52 </Field>
53
54 <button>Submit</button>
55 </Form>
56 );
57};
58
59export default Demo;
60```
61
62## 🔥 API
63
64We use typescript to create the Type definition. You can view directly in IDE. But you can still check the type definition [here](https://github.com/react-component/field-form/blob/master/src/interface.ts).
65
66### Form
67
68| Prop | Description | Type | Default |
69| ---------------- | -------------------------------------------------- | -------------------------------------------- | ---------------- |
70| component | Customize Form render component | string \| Component \| false | form |
71| fields | Control Form fields status. Only use when in Redux | [FieldData](#fielddata)[] | - |
72| form | Set form instance created by `useForm` | [FormInstance](#useform) | `Form.useForm()` |
73| initialValues | Initial value of Form | Object | - |
74| name | Config name with [FormProvider](#formprovider) | string | - |
75| preserve | Preserve value when field removed | boolean | false |
76| validateMessages | Set validate message template | [ValidateMessages](#validatemessages) | - |
77| onFieldsChange | Trigger when any value of Field changed | (changedFields, allFields) => void | - |
78| onFinish | Trigger when form submit and success | (values) => void | - |
79| onFinishFailed | Trigger when form submit and failed | ({ values, errorFields, outOfDate }) => void | - |
80| onValuesChange | Trigger when any value of Field changed | (changedValues, values) => void | - |
81
82### Field
83
84| Prop | Description | Type | Default |
85| ----------------- | ----------------------------------------------------------------------------- | ------------------------------------------- | -------- |
86| dependencies | Will re-render if dependencies changed | [NamePath](#namepath)[] | - |
87| getValueFromEvent | Specify how to get value from event | (..args: any[]) => any | - |
88| getValueProps | Customize additional props with value. This prop will disable `valuePropName` | (value) => any | - |
89| initialValue | Field initial value | any | - |
90| name | Field name path | [NamePath](#namepath) | - |
91| normalize | Normalize value before update | (value, prevValue, prevValues) => any | - |
92| preserve | Preserve value when field removed | boolean | false |
93| rules | Validate rules | [Rule](#rule)[] | - |
94| shouldUpdate | Check if Field should update | boolean \| (prevValues, nextValues) => boolean | - |
95| trigger | Collect value update by event trigger | string | onChange |
96| validateTrigger | Config trigger point with rule validate | string \| string[] | onChange |
97| valuePropName | Config value mapping prop with element | string | value |
98
99### List
100
101| Prop | Description | Type | Default |
102| -------- | ------------------------------- | ------------------------------------------------------------------------------------------------------- | ------- |
103| name | List field name path | [NamePath](#namepath)[] | - |
104| children | Render props for listing fields | (fields: { name: [NamePath](#namepath) }[], operations: [ListOperations](#listoperations)) => ReactNode | - |
105
106### useForm
107
108Form component default create an form instance by `Form.useForm`. But you can create it and pass to Form also. This allow you to call some function on the form instance.
109
110```jsx | pure
111const Demo = () => {
112 const [form] = Form.useForm();
113 return <Form form={form} />;
114};
115```
116
117For class component user, you can use `ref` to get form instance:
118
119```jsx | pure
120class Demo extends React.Component {
121 setRef = form => {
122 // Form instance here
123 };
124
125 render() {
126 return <Form ref={this.setRef} />;
127 }
128}
129```
130
131| Prop | Description | Type |
132| ----------------- | ------------------------------------------ | -------------------------------------------------------------------------- |
133| getFieldValue | Get field value by name path | (name: [NamePath](#namepath)) => any |
134| getFieldsValue | Get list of field values by name path list | (nameList?: ([NamePath](#namepath)[]) => any) \| true |
135| getFieldError | Get field errors by name path | (name: [NamePath](#namepath)) => string[] |
136| getFieldsError | Get list of field errors by name path list | (nameList?: [NamePath](#namepath)[]) => FieldError[] |
137| isFieldsTouched | Check if list of fields are touched | (nameList?: [NamePath](#namepath)[], allTouched?: boolean) => boolean |
138| isFieldTouched | Check if a field is touched | (name: [NamePath](#namepath)) => boolean |
139| isFieldValidating | Check if a field is validating | (name: [NamePath](#namepath)) => boolean |
140| resetFields | Reset fields status | (fields?: [NamePath](#namepath)[]) => void |
141| setFields | Set fields status | (fields: FieldData[]) => void |
142| setFieldsValue | Set fields value | (values) => void |
143| submit | Trigger form submit | () => void |
144| validateFields | Trigger fields to validate | (nameList?: [NamePath](#namepath)[], options?: ValidateOptions) => Promise |
145
146### FormProvider
147
148| Prop | Description | Type | Default |
149| ---------------- | ----------------------------------------- | ---------------------------------------- | ------- |
150| validateMessages | Config global `validateMessages` template | [ValidateMessages](#validatemessages) | - |
151| onFormChange | Trigger by named form fields change | (name, { changedFields, forms }) => void | - |
152| onFormFinish | Trigger by named form fields finish | (name, { values, forms }) => void | - |
153
154## 📋 Interface
155
156### NamePath
157
158| Type |
159| ---------------------------------------- |
160| string \| number \| (string \| number)[] |
161
162### FieldData
163
164| Prop | Type |
165| ---------- | ---------------------------------------- |
166| touched | boolean |
167| validating | boolean |
168| errors | string[] |
169| name | string \| number \| (string \| number)[] |
170| value | any |
171
172### Rule
173
174| Prop | Type |
175| --------------- | ----------------------------------------------------------------------------------------------- |
176| enum | any[] |
177| len | number |
178| max | number |
179| message | string |
180| min | number |
181| pattern | RegExp |
182| required | boolean |
183| transform | (value) => any |
184| type | string |
185| validator | ([rule](#rule), value, callback: (error?: string) => void, [form](#useform)) => Promise \| void |
186| whitespace | boolean |
187| validateTrigger | string \| string[] |
188
189#### validator
190
191To keep sync with `rc-form` legacy usage of `validator`, we still provides `callback` to trigger validate finished. But in `rc-field-form`, we strongly recommend to return a Promise instead.
192
193### ListOperations
194
195| Prop | Type |
196| ------ | ------------------------ |
197| add | (initValue: any) => void |
198| remove | (index: number) => void |
199
200### ValidateMessages
201
202Validate Messages provides a list of error template. You can ref [here](https://github.com/react-component/field-form/blob/master/src/utils/messages.ts) for fully default templates.
203
204| Prop | Description |
205| ------- | ------------------- |
206| enum | Rule `enum` prop |
207| len | Rule `len` prop |
208| max | Rule `max` prop |
209| min | Rule `min` prop |
210| name | Field name |
211| pattern | Rule `pattern` prop |
212| type | Rule `type` prop |
213
214## Different with `rc-form`
215
216`rc-field-form` is try to keep sync with `rc-form` in api level, but there still have something to change:
217
218### 1. Field will not keep snyc with `initialValues` when un-touched
219
220In `rc-form`, field value will get from `initialValues` if user not operate on it.
221It's a bug but user use as a feature which makes fixing will be a breaking change and we have to keep it.
222In Field Form, this bug will not exist anymore. If you want to change a field value, use `setFieldsValue` instead.
223
224### 2. Remove Field will not clean up related value
225
226We do lots of logic to clean up the value when Field removed before. But with user feedback, remove exist value increase the additional work to keep value back with conditional field.
227
228### 3. Nest name use array instead of string
229
230In `rc-form`, we support like `user.name` to be a name and convert value to `{ user: { name: 'Bamboo' } }`. This makes '.' always be the route of variable, this makes developer have to do additional work if name is real contains a point like `app.config.start` to be `app_config_start` and parse back to point when submit.
231
232Field Form will only trade `['user', 'name']` to be `{ user: { name: 'Bamboo' } }`, and `user.name` to be `{ ['user.name']: 'Bamboo' }`.
233
234### 4. Remove `validateFieldsAndScroll`
235
236Since `findDomNode` is marked as warning in [StrictMode](https://reactjs.org/docs/strict-mode.html#warning-about-deprecated-finddomnode-usage). It seems over control of Form component.
237We decide to remove `validateFieldsAndScroll` method and you should handle it with you own logic:
238
239```jsx | pure
240<Form>
241 <Field name="username">
242 <input ref={this.inputRef} />
243 </Field>
244</Form>
245```
246
247### 5. `getFieldsError` always return array
248
249`rc-form` returns `null` when no error happen. This makes user have to do some additional code like:
250
251```js | pure
252(form.getFieldsError('fieldName') || []).forEach(() => {
253 // Do something...
254});
255```
256
257Now `getFieldsError` will return `[]` if no errors.
258
259### 6. Remove `callback` with `validateFields`
260
261Since ES8 is support `async/await`, that's no reason not to use it. Now you can easily handle your validate logic:
262
263```js | pure
264async function() {
265 try {
266 const values = await form.validateFields();
267 console.log(values);
268 } catch (errorList) {
269 errorList.forEach(({ name, errors }) => {
270 // Do something...
271 });
272 }
273}
274```
275
276**Notice: Now if your validator return an `Error(message)`, not need to get error by `e => e.message`. FieldForm will handle this.**
277
278### 7. `preserve` is default to false
279
280In `rc-form` you should use `preserve` to keep a value cause Form will auto remove a value from Field removed. Field Form will always keep the value in the Form whatever Field removed. But you can still use `preserve=false` to disable value keeping since `1.5.0`.
281
282### 8. `setFields` not trigger `onFieldsChange` and `setFieldsValue` not trigger `onValuesChange`
283
284In `rc-form`, we hope to help user auto trigger change event by setting to make redux dispatch easier, but it's not good design since it makes code logic couping.
285
286Additionally, user control update trigger `onFieldsChange` & `onValuesChange` event has potential dead loop risk.