Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add StateForm #292

Closed
wants to merge 50 commits into from
Closed
Show file tree
Hide file tree
Changes from 46 commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
9b28f9d
init StateForm
zombieJ May 17, 2019
856f06b
tmp test
zombieJ May 18, 2019
5239a95
External store
zombieJ May 18, 2019
19680c1
support render props
zombieJ May 18, 2019
8039e35
add now
zombieJ May 18, 2019
d6ac84c
lock rc-tools version
zombieJ May 18, 2019
46744ab
sample of useForm
zombieJ May 18, 2019
115dcbd
use getFieldsValue instead of getStore
zombieJ May 19, 2019
a8ea903
render props also support component update check
zombieJ May 19, 2019
3a84a85
adjust value check logic
zombieJ May 20, 2019
6179901
add trigger
zombieJ May 20, 2019
725d772
fix ts error
zombieJ May 20, 2019
cbaa78f
register Field directly
zombieJ May 20, 2019
ae1b74b
add isSimular
zombieJ May 20, 2019
d8c8745
update demo
zombieJ May 20, 2019
a5f178a
render props validate
zombieJ May 20, 2019
6603f3e
cache error
zombieJ May 20, 2019
803aa91
remove should component update
zombieJ May 21, 2019
d7222eb
add description
zombieJ May 21, 2019
d366fb4
update validate logic
zombieJ May 21, 2019
b5a293c
update gitignore
zombieJ May 21, 2019
c9e8172
update submit logic
zombieJ May 28, 2019
10db2e1
add keys
zombieJ May 28, 2019
7a8420f
update setFieldsValue logic
zombieJ May 28, 2019
34db7ce
support lazy notify Field
zombieJ May 28, 2019
0069125
style layout
zombieJ May 28, 2019
b892fa6
wrap useForm
zombieJ May 28, 2019
885dd1d
fix error logic
zombieJ May 28, 2019
c76d008
support single validateTrigger
zombieJ May 28, 2019
ad88444
add getFieldValue
zombieJ May 29, 2019
2a97baa
support touch
zombieJ May 29, 2019
5ea94dc
support isFieldValidating
zombieJ May 29, 2019
1b93e5d
fix validating not works
zombieJ May 29, 2019
b37f375
support initial values
zombieJ May 29, 2019
bf7d901
add reset interface
zombieJ May 29, 2019
8e7fe87
support reset
zombieJ May 29, 2019
d5b7add
support setFields
zombieJ May 30, 2019
3011cc9
refactor
zombieJ May 30, 2019
a1571c9
rename interface
zombieJ May 31, 2019
4346314
support dependencies
zombieJ Jun 3, 2019
558da19
update example
zombieJ Jun 3, 2019
00e4272
opt errors
zombieJ Jun 3, 2019
7fa6008
add props for redux
zombieJ Jun 3, 2019
933a255
supprot redux
zombieJ Jun 3, 2019
b77f543
fix errors
zombieJ Jun 4, 2019
b09c682
fix check meta logic
zombieJ Jun 4, 2019
2aac0b1
update demo
zombieJ Jun 4, 2019
56e3705
support list
zombieJ Jun 4, 2019
45871ab
suport list remove
zombieJ Jun 4, 2019
18f820f
wrap entities api
zombieJ Jun 4, 2019
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 4 additions & 1 deletion .gitignore
Expand Up @@ -23,5 +23,8 @@ node_modules
build
dist
lib
es
coverage
yarn.lock
yarn.lock
package-lock.json
storybook
57 changes: 57 additions & 0 deletions examples/StateForm-basic.js
@@ -0,0 +1,57 @@
import React from 'react';
import StateForm from '../src/StateForm';
import Input from './components/Input';

const { Field } = StateForm;

const list = new Array(1111).fill();

export default class Demo extends React.Component {
state = {};

render() {
return (
<div>
<h3>State Form ({list.length} inputs)</h3>
<StateForm>
<Field name="username">
<Input placeholder="Username" />
</Field>
<Field name="password">
<Input placeholder="Password" />
</Field>
<Field name="username">
<Input placeholder="Shadow of Username" />
</Field>
<Field name={[ 'path1', 'path2' ]}>
<Input placeholder="nest" />
</Field>
<Field name={[ 'renderProps' ]}>
{(control) => (
<div>
I am render props
<Input {...control} placeholder="render props" />
</div>
)}
</Field>

<h4>Show additional field when `username` is `111`</h4>
<Field name="condition" shouldUpdate={(prev, next) => prev.username !== next.username}>
{(control, meta, context) => {
const { username } = context.getFieldsValue();
return username === '111' ? (
<Input {...control} placeholder="I am secret!" />
) : null;
}}
</Field>

{list.map((_, index) => (
<Field key={index} name={`field_${index}`}>
<Input placeholder={`field_${index}`} />
</Field>
))}
</StateForm>
</div>
);
}
}
31 changes: 31 additions & 0 deletions examples/StateForm-layout.js
@@ -0,0 +1,31 @@
/* eslint-disable jsx-a11y/label-has-associated-control, react/prop-types */

import React from 'react';
import StateForm from '../src/StateForm';
import Input from './components/Input';
import LabelField from './components/LabelField';

const list = new Array(1111).fill();

export default class Demo extends React.Component {
state = {};

render() {
return (
<div>
<h3>State Form ({list.length} inputs)</h3>
<StateForm>
<LabelField name="username">
<Input placeholder="Username" />
</LabelField>
<LabelField name="password">
<Input placeholder="Password" />
</LabelField>
<LabelField name={['path1', 'path2']} label="Nest Path" rules={[ { required: true } ]}>
<Input placeholder="nest" />
</LabelField>
</StateForm>
</div>
);
}
}
79 changes: 79 additions & 0 deletions examples/StateForm-redux.tsx
@@ -0,0 +1,79 @@
/* eslint-disable react/prop-types */

import React from 'react';
import { connect, Provider } from 'react-redux';
import { createStore } from 'redux';
import StateForm from '../src/StateForm';
import Input from './components/Input';
import LabelField from './components/LabelField';

function formReducer(fields = [], action: any) {
switch (action.type) {
case 'updateFields':
return [...action.fields];
default:
return fields;
}
}

const store = createStore(formReducer);

let App: any = ({ dispatch, fields }) => {
console.log('=>', fields);

return (
<StateForm
fields={fields}
onValuesChange={(changedValues, allValues) => {
console.log('Value Change:', changedValues, allValues);
}}
onFieldsChange={(changedFields, allFields) => {
console.log('Field Change:', changedFields, allFields);
dispatch({
type: 'updateFields',
fields: allFields,
});
}}
>
<h3>Redux Form</h3>
<p>It's no need to put data into redux store. But you can still do this.</p>

<LabelField name="field">
<Input />
</LabelField>

<LabelField name="required" placeholder="required" rules={[{ required: true }]}>
<Input />
</LabelField>

<button
onClick={() => {
dispatch({
type: 'updateFields',
fields: [
{
name: 'field',
value: 'redux it!',
touched: true,
validating: true,
},
],
});
}}
>
dispatch to change
</button>
</StateForm>
);
};
App = connect((fields: any) => ({ fields }))(App);

const Demo = () => {
return (
<Provider store={store}>
<App />
</Provider>
);
};

export default Demo;
62 changes: 62 additions & 0 deletions examples/StateForm-renderProps.js
@@ -0,0 +1,62 @@
/* eslint-disable jsx-a11y/label-has-associated-control */
import React from 'react';
import StateForm from '../src/StateForm';
import Input from './components/Input';

const { Field } = StateForm;

const list = new Array(1111).fill();

export default class Demo extends React.Component {
state = {};

render() {
return (
<div>
<h3>Render Props ({list.length} inputs)</h3>
<p>Render Props is easy to use but bad performance</p>
<StateForm>
{(store) => {
return (
<React.Fragment>
{JSON.stringify(store, null, 2)}
<Field name="field_1">
<Input placeholder="Field 1" />
</Field>
<Field name="field_1">
<Input placeholder="Shadow of Field 1" />
</Field>
<Field name="field_2">
<Input placeholder="Field 2" />
</Field>

<h4>Show additional field when field 1 is `222`</h4>
{store.field_1 === '222' ? (
<Field name="secret">
<Input placeholder="Field Secret!" />
</Field>
) : 'Nothing yet...'}

<Field name="bad">
{(control) => {
return (
<div>
Field Render Props: <Input {...control} />
</div>
);
}}
</Field>

{list.map((_, index) => (
<Field key={index} name={`list_field_${index}`}>
<Input placeholder={`list_field_${index}`} />
</Field>
))}
</React.Fragment>
);
}}
</StateForm>
</div>
);
}
}
72 changes: 72 additions & 0 deletions examples/StateForm-reset.js
@@ -0,0 +1,72 @@
/* eslint-disable react/prop-types */
import React from 'react';
import StateForm from '../src/StateForm';
import Input from './components/Input';

const { Field } = StateForm;

function Item({ children, ...restProps }) {
return (
<Field {...restProps}>
{(control, meta) => {
return (
<div>
<div>{React.cloneElement(children, { ...control })}</div>

{meta.touched && 'touched!'}
{meta.validating && 'validating!'}
{meta.errors}
</div>
);
}}
</Field>
);
}

const Demo = () => {
const [form] = StateForm.useForm();
return (
<div>
<h3>Reset / Set Form</h3>
<StateForm form={form} initialValues={{ username: 'strange', path1: { path2: '233' } }}>
<Item name="username" rules={[{ required: true }]}>
<Input placeholder="Username" />
</Item>
<Item name="password" rules={[{ required: true }]}>
<Input placeholder="Password" />
</Item>
<Item name={['path1', 'path2']} rules={[{ required: true }]}>
<Input placeholder="nest" />
</Item>
<button
type="button"
onClick={() => {
form.resetFields(['password']);
}}
>
Reset Password
</button>
<button
type="button"
onClick={() => {
form.resetFields();
}}
>
Reset All
</button>
<button
type="button"
onClick={() => {
form.setFields([
{ name: 'password', value: 'ERROR ME', touched: false, errors: ['Good for you!', 'Good for me!'] },
]);
}}
>
Set Password with Errors
</button>
</StateForm>
</div>
);
};

export default Demo;
49 changes: 49 additions & 0 deletions examples/StateForm-useForm.js
@@ -0,0 +1,49 @@
import React from 'react';
import StateForm from '../src/StateForm';
import Input from './components/Input';

const { Field, useForm } = StateForm;

const list = new Array(0).fill();

export default () => {
const [form] = useForm();

return (
<div>
<h3>useForm ({list.length} inputs)</h3>

<button type="button" onClick={() => {
form.setFieldsValue({
username: 'light',
password: 'bamboo',
});
}}>
Fill Values
</button>

<StateForm form={form}>
<React.Fragment>
<Field name="username">
<Input placeholder="Username" />
</Field>
<Field name="password">
<Input placeholder="Password" />
</Field>
<Field name="username">
<Input placeholder="Shadow of Username" />
</Field>
<Field name={[ 'path1', 'path2' ]}>
<Input placeholder="nest" />
</Field>

{list.map((_, index) => (
<Field key={index} name={`field_${index}`}>
<Input placeholder={`field_${index}`} />
</Field>
))}
</React.Fragment>
</StateForm>
</div>
);
};