Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 10 additions & 8 deletions .eslintrc.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
const base = require('father/template/.eslintrc.js');
const base = require('@umijs/fabric/dist/eslint');

base.rules['no-template-curly-in-string'] = 0;
base.rules['promise/always-return'] = 0;
base.rules['promise/catch-or-return'] = 0;
base.rules['promise/no-callback-in-promise'] = 0;
base.rules['prefer-promise-reject-errors'] = 0;

module.exports = base;
module.exports = {
...base,
rules: {
...base.rules,
'no-template-curly-in-string': 0,
'prefer-promise-reject-errors': 0,
'react/no-array-index-key': 0,
},
};
6 changes: 0 additions & 6 deletions .prettierrc

This file was deleted.

112 changes: 60 additions & 52 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,33 +61,35 @@ We use typescript to create the Type definition. You can view directly in IDE. B

## Form

| Prop | Description | Type | Default |
| --- | --- | --- | --- |
| fields | Control Form fields status. Only use when in Redux | [FieldData](#fielddata)[] | - |
| form | Set form instance created by `useForm` | [FormInstance](#useform) | `Form.useForm()` |
| initialValues | Initial value of Form | Object | - |
| name | Config name with [FormProvider](#formprovider) | string | - |
| validateMessages | Set validate message template | [ValidateMessages](#validatemessages) | - |
| onFieldsChange | Trigger when any value of Field changed | (changedFields, allFields): void | - |
| onValuesChange | Trigger when any value of Field changed | (changedValues, values): void | - |
| Prop | Description | Type | Default |
| ---------------- | -------------------------------------------------- | ------------------------------------- | ---------------- |
| fields | Control Form fields status. Only use when in Redux | [FieldData](#fielddata)[] | - |
| form | Set form instance created by `useForm` | [FormInstance](#useform) | `Form.useForm()` |
| initialValues | Initial value of Form | Object | - |
| name | Config name with [FormProvider](#formprovider) | string | - |
| validateMessages | Set validate message template | [ValidateMessages](#validatemessages) | - |
| onFieldsChange | Trigger when any value of Field changed | (changedFields, allFields): void | - |
| onValuesChange | Trigger when any value of Field changed | (changedValues, values): void | - |

## Field

| Prop | Description | Type | Default |
| --- | --- | --- | --- |
| dependencies | Will re-render if dependencies changed | [NamePath](#namepath)[] | - |
| name | Field name path | [NamePath](#namepath) | - |
| rules | Validate rules | [Rule](#rule)[] | - |
| shouldUpdate | Check if Field should update | (prevValues, nextValues): boolean | - |
| trigger | Collect value update by event trigger | string | onChange |
| validateTrigger | Config trigger point with rule validate | string \| string[] | onChange |
| Prop | Description | Type | Default |
| ----------------- | --------------------------------------- | ------------------------------------- | -------- |
| dependencies | Will re-render if dependencies changed | [NamePath](#namepath)[] | - |
| getValueFromEvent | Specify how to get value from event | (..args: any[]) => any | - |
| name | Field name path | [NamePath](#namepath) | - |
| normalize | Normalize value before update | (value, prevValue, prevValues) => any | - |
| rules | Validate rules | [Rule](#rule)[] | - |
| shouldUpdate | Check if Field should update | (prevValues, nextValues): boolean | - |
| trigger | Collect value update by event trigger | string | onChange |
| validateTrigger | Config trigger point with rule validate | string \| string[] | onChange |

## List

| Prop | Description | Type | Default |
| --- | --- | --- | --- |
| name | List field name path | [NamePath](#namepath)[] | - |
| children | Render props for listing fields | (fields: { name: [NamePath](#namepath) }[], operations: [ListOperations](#listoperations)): ReactNode | - |
| Prop | Description | Type | Default |
| -------- | ------------------------------- | ----------------------------------------------------------------------------------------------------- | ------- |
| name | List field name path | [NamePath](#namepath)[] | - |
| children | Render props for listing fields | (fields: { name: [NamePath](#namepath) }[], operations: [ListOperations](#listoperations)): ReactNode | - |

## useForm

Expand All @@ -114,26 +116,26 @@ class Demo extends React.Component {
}
```

| Prop | Description | Type |
| --- | --- | --- |
| getFieldValue | Get field value by name path | (name: [NamePath](#namepath)) => any |
| getFieldsValue | Get list of field values by name path list | (nameList?: [NamePath](#namepath)[]) => any |
| getFieldError | Get field errors by name path | (name: [NamePath](#namepath)) => string[] |
| getFieldsError | Get list of field errors by name path list | (nameList?: [NamePath](#namepath)[]) => FieldError[] |
| isFieldsTouched | Check if list of fields are touched | (nameList?: [NamePath](#namepath)[]) => boolean |
| isFieldTouched | Check if a field is touched | (name: [NamePath](#namepath)) => boolean |
| isFieldValidating | Check if a field is validating | (name: [NamePath](#namepath)) => boolean |
| resetFields | Reset fields status | (fields?: [NamePath](#namepath)[]) => void |
| setFields | Set fields status | (fields: FieldData[]) => void |
| setFieldsValue | Set fields value | (values) => void |
| validateFields | Trigger fields to validate | (nameList?: [NamePath](#namepath)[], options?: ValidateOptions) => Promise |
| Prop | Description | Type |
| ----------------- | ------------------------------------------ | -------------------------------------------------------------------------- |
| getFieldValue | Get field value by name path | (name: [NamePath](#namepath)) => any |
| getFieldsValue | Get list of field values by name path list | (nameList?: [NamePath](#namepath)[]) => any |
| getFieldError | Get field errors by name path | (name: [NamePath](#namepath)) => string[] |
| getFieldsError | Get list of field errors by name path list | (nameList?: [NamePath](#namepath)[]) => FieldError[] |
| isFieldsTouched | Check if list of fields are touched | (nameList?: [NamePath](#namepath)[]) => boolean |
| isFieldTouched | Check if a field is touched | (name: [NamePath](#namepath)) => boolean |
| isFieldValidating | Check if a field is validating | (name: [NamePath](#namepath)) => boolean |
| resetFields | Reset fields status | (fields?: [NamePath](#namepath)[]) => void |
| setFields | Set fields status | (fields: FieldData[]) => void |
| setFieldsValue | Set fields value | (values) => void |
| validateFields | Trigger fields to validate | (nameList?: [NamePath](#namepath)[], options?: ValidateOptions) => Promise |

## FormProvider

| Prop | Description | Type | Default |
| --- | --- | --- | --- |
| validateMessages | Config global `validateMessages` template | [ValidateMessages](#validatemessages) | - |
| onFormChange | Trigger by named form fields change | (name, { changedFields, forms }) => void | - |
| Prop | Description | Type | Default |
| ---------------- | ----------------------------------------- | ---------------------------------------- | ------- |
| validateMessages | Config global `validateMessages` template | [ValidateMessages](#validatemessages) | - |
| onFormChange | Trigger by named form fields change | (name, { changedFields, forms }) => void | - |

## Interface

Expand All @@ -155,20 +157,20 @@ class Demo extends React.Component {

### Rule

| Prop | Type |
| --- | --- |
| enum | any[] |
| len | number |
| max | number |
| message | string |
| min | number |
| pattern | RegExp |
| required | boolean |
| transform | (value) => any |
| type | string |
| validator | ([rule](#rule), value, callback: (error?: string) => void, [form](#useform)) => Promise \| void |
| whitespace | boolean |
| validateTrigger | string \| string[] |
| Prop | Type |
| --------------- | ----------------------------------------------------------------------------------------------- |
| enum | any[] |
| len | number |
| max | number |
| message | string |
| min | number |
| pattern | RegExp |
| required | boolean |
| transform | (value) => any |
| type | string |
| validator | ([rule](#rule), value, callback: (error?: string) => void, [form](#useform)) => Promise \| void |
| whitespace | boolean |
| validateTrigger | string \| string[] |

#### validator

Expand Down Expand Up @@ -199,6 +201,12 @@ Validate Messages provides a list of error template. You can ref [here](https://

`rc-field-form` is try to keep sync with `rc-form` in api level, but there still have something to change:

## 🔥 Field will not keep snyc with `initialValues` when un-touched

In `rc-form`, field value will get from `initialValues` if user not operate on it.
It's a bug but user use as a feature which makes fixing will be a breaking change and we have to keep it.
In Field Form, this bug will not exist anymore. If you want to change a field value, use `setFieldsValue` instead.

## 🔥 Remove Field will not clean up related value

We 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.
Expand Down
6 changes: 3 additions & 3 deletions examples/StateForm-renderProps.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@ export default class Demo extends React.Component {
<h3>Render Props ({list.length} inputs)</h3>
<p>Render Props is easy to use but bad performance</p>
<StateForm>
{(store) => {
{(values) => {
return (
<React.Fragment>
{JSON.stringify(store, null, 2)}
{JSON.stringify(values, null, 2)}
<Field name="field_1">
<Input placeholder="Field 1" />
</Field>
Expand All @@ -31,7 +31,7 @@ export default class Demo extends React.Component {
</Field>

<h4>Show additional field when field 1 is `222`</h4>
{store.field_1 === '222' ? (
{values.field_1 === '222' ? (
<Field name="secret">
<Input placeholder="Field Secret!" />
</Field>
Expand Down
7 changes: 4 additions & 3 deletions examples/StateForm-validate-perf.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,14 +49,14 @@ export default class Demo extends React.Component {
dependencies={['password']}
rules={[
{ required: true },
{
async validator(_, value, __, { getFieldValue }) {
({ getFieldValue }) => ({
async validator(_, value) {
if (getFieldValue('password') !== value) {
return Promise.reject('password2 is not same as password');
}
return Promise.resolve();
},
},
}),
]}
>
<Input placeholder="password 2" />
Expand All @@ -67,6 +67,7 @@ export default class Demo extends React.Component {
label="Full of rules"
rules={[
{ required: true },
{ required: true, message: <h1>我是 ReactNode</h1> },
{ type: 'number' },
{ type: 'enum', enum: ['aaa', 'bbb'] },
{ type: 'date' },
Expand Down
28 changes: 16 additions & 12 deletions examples/StateForm-validate.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,11 @@ import Input from './components/Input';
const { Field } = StateForm;

const Error = ({ children }) => (
<ul style={{ color: 'red' }}>{children.map((error) => <li>{error}</li>)}</ul>
<ul style={{ color: 'red' }}>
{children.map(error => (
<li>{error}</li>
))}
</ul>
);

const FieldState = ({ form, name }) => {
Expand All @@ -23,7 +27,7 @@ const FieldState = ({ form, name }) => {
};

export default class Demo extends React.Component {
onFinish = (values) => {
onFinish = values => {
console.log('Finish:', values);
};

Expand All @@ -43,7 +47,7 @@ export default class Demo extends React.Component {

return (
<React.Fragment>
<Field name="username" rules={[ { required: true } ]}>
<Field name="username" rules={[{ required: true }]}>
<Input
placeholder="Username"
onChange={({ target: { value } }) => {
Expand All @@ -58,16 +62,16 @@ export default class Demo extends React.Component {
name="password"
rules={[
{ required: true },
{
validator(_, __, callback, context) {
context => ({
validator(_, __, callback) {
if (context.isFieldTouched('password2')) {
context.validateFields([ 'password2' ]);
context.validateFields(['password2']);
callback();
return;
}
callback();
},
},
}),
]}
>
<Input placeholder="Password" />
Expand All @@ -79,23 +83,23 @@ export default class Demo extends React.Component {
name="password2"
rules={[
{ required: true },
{
validator(rule, value, callback, context) {
context => ({
validator(rule, value, callback) {
const { password } = context.getFieldsValue();
if (password !== value) {
callback('Not Same as password1!!!');
}
callback();
},
},
}),
]}
>
<Input placeholder="Password 2" />
</Field>
<FieldState form={form} name="password2" />
<Error>{password2Error}</Error>

<Field name="renderProps" rules={[ { required: true } ]}>
<Field name="renderProps" rules={[{ required: true }]}>
{(control, meta) => {
return (
<div>
Expand All @@ -110,7 +114,7 @@ export default class Demo extends React.Component {

<Field
name="validateTrigger"
validateTrigger={[ 'onSubmit', 'onChange' ]}
validateTrigger={['onSubmit', 'onChange']}
rules={[
{ required: true, validateTrigger: 'onSubmit' },
{
Expand Down
4 changes: 2 additions & 2 deletions examples/components/LabelField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ const { Field } = StateForm;

const Error = ({ children }) => (
<ul style={{ color: 'red' }}>
{children.map((error: string) => (
<li key={error}>{error}</li>
{children.map((error: React.ReactNode, index: number) => (
<li key={index}>{error}</li>
))}
</ul>
);
Expand Down
Loading