Skip to content

Commit 5b97316

Browse files
authored
feat: support getValueProps (#110)
* add getValueProps * test case * update readme
1 parent b729ea5 commit 5b97316

File tree

3 files changed

+51
-61
lines changed

3 files changed

+51
-61
lines changed

README.md

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -76,17 +76,18 @@ We use typescript to create the Type definition. You can view directly in IDE. B
7676

7777
## Field
7878

79-
| Prop | Description | Type | Default |
80-
| ----------------- | --------------------------------------- | ----------------------------------------- | -------- |
81-
| dependencies | Will re-render if dependencies changed | [NamePath](#namepath)[] | - |
82-
| getValueFromEvent | Specify how to get value from event | (..args: any[]) => any | - |
83-
| name | Field name path | [NamePath](#namepath) | - |
84-
| normalize | Normalize value before update | (value, prevValue, prevValues) => any | - |
85-
| rules | Validate rules | [Rule](#rule)[] | - |
86-
| shouldUpdate | Check if Field should update | true \| (prevValues, nextValues): boolean | - |
87-
| trigger | Collect value update by event trigger | string | onChange |
88-
| validateTrigger | Config trigger point with rule validate | string \| string[] | onChange |
89-
| valuePropName | Config value mapping prop with element | string | value |
79+
| Prop | Description | Type | Default |
80+
| ----------------- | ----------------------------------------------------------------------------- | ----------------------------------------- | -------- |
81+
| dependencies | Will re-render if dependencies changed | [NamePath](#namepath)[] | - |
82+
| getValueFromEvent | Specify how to get value from event | (..args: any[]) => any | - |
83+
| getValueProps | Customize additional props with value. This prop will disable `valuePropName` | (value) => any | - |
84+
| name | Field name path | [NamePath](#namepath) | - |
85+
| normalize | Normalize value before update | (value, prevValue, prevValues) => any | - |
86+
| rules | Validate rules | [Rule](#rule)[] | - |
87+
| shouldUpdate | Check if Field should update | true \| (prevValues, nextValues): boolean | - |
88+
| trigger | Collect value update by event trigger | string | onChange |
89+
| validateTrigger | Config trigger point with rule validate | string \| string[] | onChange |
90+
| valuePropName | Config value mapping prop with element | string | value |
9091

9192
## List
9293

src/Field.tsx

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ export interface InternalFieldProps {
6868
validateTrigger?: string | string[] | false;
6969
validateFirst?: boolean;
7070
valuePropName?: string;
71+
getValueProps?: (value: StoreValue) => object;
7172
messageVariables?: Record<string, string>;
7273
onReset?: () => void;
7374
}
@@ -366,18 +367,26 @@ class Field extends React.Component<InternalFieldProps, FieldState> implements F
366367
};
367368

368369
public getControlled = (childProps: ChildProps = {}) => {
369-
const { trigger, validateTrigger, getValueFromEvent, normalize, valuePropName } = this.props;
370+
const {
371+
trigger,
372+
validateTrigger,
373+
getValueFromEvent,
374+
normalize,
375+
valuePropName,
376+
getValueProps,
377+
} = this.props;
370378
const namePath = this.getNamePath();
371379
const { getInternalHooks, getFieldsValue }: InternalFormInstance = this.context;
372380
const { dispatch } = getInternalHooks(HOOK_MARK);
373381
const value = this.getValue();
382+
const mergedGetValueProps = getValueProps || ((val: StoreValue) => ({ [valuePropName]: val }));
374383

375384
// eslint-disable-next-line @typescript-eslint/no-explicit-any
376385
const originTriggerFunc: any = childProps[trigger];
377386

378387
const control = {
379388
...childProps,
380-
[valuePropName]: value,
389+
...mergedGetValueProps(value),
381390
};
382391

383392
// Add trigger

tests/index.test.js

Lines changed: 28 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,7 @@ describe('Form.Basic', () => {
4242

4343
it('use component', () => {
4444
const MyComponent = ({ children }) => <div>{children}</div>;
45-
const wrapper = mount(
46-
<Form component={MyComponent}>{renderContent()}</Form>,
47-
);
45+
const wrapper = mount(<Form component={MyComponent}>{renderContent()}</Form>);
4846
expect(wrapper.find('form').length).toBe(0);
4947
expect(wrapper.find(MyComponent).length).toBe(1);
5048
expect(wrapper.find('input').length).toBe(2);
@@ -111,11 +109,7 @@ describe('Form.Basic', () => {
111109
form = instance;
112110
}}
113111
>
114-
<Field
115-
name="username"
116-
rules={[{ required: true }]}
117-
onReset={onReset}
118-
>
112+
<Field name="username" rules={[{ required: true }]} onReset={onReset}>
119113
<Input />
120114
</Field>
121115
</Form>
@@ -137,9 +131,7 @@ describe('Form.Basic', () => {
137131

138132
await changeValue(getField(wrapper, 'username'), '');
139133
expect(form.getFieldValue('username')).toEqual('');
140-
expect(form.getFieldError('username')).toEqual([
141-
"'username' is required",
142-
]);
134+
expect(form.getFieldError('username')).toEqual(["'username' is required"]);
143135
expect(form.isFieldTouched('username')).toBeTruthy();
144136

145137
expect(onReset).not.toHaveBeenCalled();
@@ -183,9 +175,7 @@ describe('Form.Basic', () => {
183175
expect(form.getFieldError('username')).toEqual([]);
184176
expect(form.isFieldTouched('username')).toBeFalsy();
185177
expect(form.getFieldValue('password')).toEqual('');
186-
expect(form.getFieldError('password')).toEqual([
187-
"'password' is required",
188-
]);
178+
expect(form.getFieldError('password')).toEqual(["'password' is required"]);
189179
expect(form.isFieldTouched('password')).toBeTruthy();
190180
});
191181
});
@@ -337,13 +327,8 @@ describe('Form.Basic', () => {
337327
);
338328

339329
await changeValue(getField(wrapper), 'Bamboo');
340-
expect(onValuesChange).toHaveBeenCalledWith(
341-
{ username: 'Bamboo' },
342-
{ username: 'Bamboo' },
343-
);
344-
expect(onChange).toHaveBeenCalledWith(
345-
expect.objectContaining({ target: { value: 'Bamboo' } }),
346-
);
330+
expect(onValuesChange).toHaveBeenCalledWith({ username: 'Bamboo' }, { username: 'Bamboo' });
331+
expect(onChange).toHaveBeenCalledWith(expect.objectContaining({ target: { value: 'Bamboo' } }));
347332
});
348333

349334
it('submit', async () => {
@@ -422,19 +407,29 @@ describe('Form.Basic', () => {
422407
</div>,
423408
);
424409

425-
wrapper
426-
.find('input[type="checkbox"]')
427-
.simulate('change', { target: { checked: true } });
410+
wrapper.find('input[type="checkbox"]').simulate('change', { target: { checked: true } });
428411
await timeout();
429412
expect(form.getFieldsValue()).toEqual({ check: true });
430413

431-
wrapper
432-
.find('input[type="checkbox"]')
433-
.simulate('change', { target: { checked: false } });
414+
wrapper.find('input[type="checkbox"]').simulate('change', { target: { checked: false } });
434415
await timeout();
435416
expect(form.getFieldsValue()).toEqual({ check: false });
436417
});
437418

419+
it('getValueProps', async () => {
420+
const wrapper = mount(
421+
<div>
422+
<Form initialValues={{ test: 'bamboo' }}>
423+
<Field name="test" getValueProps={val => ({ light: val })}>
424+
<span className="anything" />
425+
</Field>
426+
</Form>
427+
</div>,
428+
);
429+
430+
expect(wrapper.find('.anything').props().light).toEqual('bamboo');
431+
});
432+
438433
it('shouldUpdate', async () => {
439434
let isAllTouched;
440435
let hasError;
@@ -450,8 +445,7 @@ describe('Form.Basic', () => {
450445
<Field shouldUpdate>
451446
{(_, __, { getFieldsError, isFieldsTouched }) => {
452447
isAllTouched = isFieldsTouched(true);
453-
hasError = getFieldsError().filter(({ errors }) => errors.length)
454-
.length;
448+
hasError = getFieldsError().filter(({ errors }) => errors.length).length;
455449

456450
return null;
457451
}}
@@ -528,9 +522,7 @@ describe('Form.Basic', () => {
528522
triggerUpdate.mockReset();
529523

530524
// Not trigger render
531-
formRef.current.setFields([
532-
{ name: 'others', value: 'no need to update' },
533-
]);
525+
formRef.current.setFields([{ name: 'others', value: 'no need to update' }]);
534526
wrapper.update();
535527
expect(triggerUpdate).not.toHaveBeenCalled();
536528

@@ -579,10 +571,7 @@ describe('Form.Basic', () => {
579571
form = instance;
580572
}}
581573
>
582-
<Field
583-
name="normal"
584-
rules={[{ validator: () => new Promise(() => {}) }]}
585-
>
574+
<Field name="normal" rules={[{ validator: () => new Promise(() => {}) }]}>
586575
{(control, meta) => {
587576
currentMeta = meta;
588577
return <Input {...control} />;
@@ -684,25 +673,16 @@ describe('Form.Basic', () => {
684673

685674
expect(
686675
form.getFieldsValue(null, meta => {
687-
expect(Object.keys(meta)).toEqual([
688-
'touched',
689-
'validating',
690-
'errors',
691-
'name',
692-
]);
676+
expect(Object.keys(meta)).toEqual(['touched', 'validating', 'errors', 'name']);
693677
return false;
694678
}),
695679
).toEqual({});
696680

697-
expect(form.getFieldsValue(null, () => true)).toEqual(
698-
form.getFieldsValue(),
699-
);
681+
expect(form.getFieldsValue(null, () => true)).toEqual(form.getFieldsValue());
700682
expect(form.getFieldsValue(null, meta => meta.touched)).toEqual({});
701683

702684
await changeValue(getField(wrapper, 0), 'Bamboo');
703-
expect(form.getFieldsValue(null, () => true)).toEqual(
704-
form.getFieldsValue(),
705-
);
685+
expect(form.getFieldsValue(null, () => true)).toEqual(form.getFieldsValue());
706686
expect(form.getFieldsValue(null, meta => meta.touched)).toEqual({
707687
username: 'Bamboo',
708688
});

0 commit comments

Comments
 (0)