Skip to content

Commit d7cfd27

Browse files
committed
feat: demonstration of adding "reset"
1 parent d7bace6 commit d7cfd27

File tree

7 files changed

+98
-13
lines changed

7 files changed

+98
-13
lines changed
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
'use client';
2+
3+
import React from 'react';
4+
import { Button, ButtonGroup, Card, Form, FormField, Input, useForm } from 'soybean-react-ui';
5+
6+
type Inputs = {
7+
info: { city: string; company: string };
8+
password: string;
9+
username: string;
10+
};
11+
12+
const initialValues = {
13+
info: {
14+
city: 'Beijing'
15+
},
16+
password: '22333'
17+
};
18+
19+
const Reset = () => {
20+
const [form] = useForm<Inputs>();
21+
22+
const handleReset = () => {
23+
form.resetFields();
24+
};
25+
26+
const handleResetUsername = () => {
27+
form.resetFields('password');
28+
};
29+
30+
return (
31+
<Card title="Reset">
32+
<Form
33+
className="w-[480px] max-sm:w-full space-y-4"
34+
form={form}
35+
initialValues={initialValues}
36+
>
37+
<FormField
38+
label="Username"
39+
name="username"
40+
>
41+
<Input placeholder="Enter username" />
42+
</FormField>
43+
44+
<FormField
45+
label="Password"
46+
name="password"
47+
>
48+
<Input placeholder="Enter password" />
49+
</FormField>
50+
51+
<FormField
52+
label="Info&City"
53+
name="info.city"
54+
>
55+
<Input placeholder="Enter info.city" />
56+
</FormField>
57+
58+
<FormField
59+
label="Info&Company"
60+
name="info.company"
61+
>
62+
<Input placeholder="Enter info.company" />
63+
</FormField>
64+
65+
<div className="flex gap-x-1">
66+
<Button onClick={handleReset}>Reset All</Button>
67+
<Button onClick={handleResetUsername}>Reset Username</Button>
68+
</div>
69+
</Form>
70+
</Card>
71+
);
72+
};
73+
74+
export default Reset;

playground/src/app/(demo)/form/page.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import Default from './modules/Default';
22
import FieldChange from './modules/FieldChange';
3+
import Reset from './modules/Reset';
34
import UseWatch from './modules/UseWatch';
45
import Validate from './modules/validate';
56
import ValidateWarning from './modules/validateWaring';
@@ -16,6 +17,8 @@ const FormPage = () => {
1617
<ValidateWarning />
1718

1819
<UseWatch />
20+
21+
<Reset />
1922
</div>
2023
);
2124
};

primitives/filed-form /src/Field.tsx

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,11 @@
33

44
import { Slot } from '@radix-ui/react-slot';
55
import { useEffect, useId, useRef, useState } from 'react';
6-
import { capitalize, getEventValue, isEqual, omitUndefined, toArray } from 'skyroc-utils';
6+
import { capitalize, getEventValue, isEqual, isNil, omitUndefined, toArray } from 'skyroc-utils';
77

88
import type { InternalFormInstance } from './FieldContext';
99
import { useFieldContext } from './FieldContext';
10+
import { ChangeTag } from './form-core/event';
1011
import type { InternalFieldProps } from './types/field';
1112
import type { StoreValue } from './types/formStore';
1213

@@ -120,8 +121,8 @@ function Field<Values = any>(props: InternalFieldProps<Values>) {
120121

121122
useEffect(() => {
122123
const unregister = registerField({
123-
changeValue: newValue => {
124-
if (!normalizedChangedRef.current) return;
124+
changeValue: (newValue, __, ___, mask) => {
125+
if (!normalizedChangedRef.current && mask === ChangeTag.Value) return;
125126

126127
normalizedChangedRef.current = false;
127128

@@ -138,7 +139,7 @@ function Field<Values = any>(props: InternalFieldProps<Values>) {
138139
if (unControlledValueChange) {
139140
unControlledValueChange(cref.current, newValue);
140141
} else {
141-
cref.current.value = newValue as any;
142+
cref.current.value = isNil(newValue) ? '' : (newValue as any);
142143
}
143144
}
144145
}

primitives/filed-form /src/FieldContext.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
import { createContext, useContext, useEffect, useState } from 'react';
55
import { flushSync } from 'react-dom';
6-
import type { AllPaths, AllPathsKeys, PathToDeepType, ShapeFromPaths } from 'skyroc-type-utils';
6+
import type { AllPaths, AllPathsKeys, DeepPartial, PathToDeepType, ShapeFromPaths } from 'skyroc-type-utils';
77
import { isArray, toArray } from 'skyroc-utils';
88

99
import type { ChangeMask, SubscribeMaskOptions } from './form-core/event';
@@ -90,7 +90,7 @@ export interface RegisterCallbackOptions<Values = any> {
9090
export interface InternalCallbacks<Values = any> {
9191
destroyForm: (clearOnDestroy?: boolean) => void;
9292
setCallbacks: (callbacks: RegisterCallbackOptions<Values>) => void;
93-
setInitialValues: (values: Partial<Values>) => void;
93+
setInitialValues: (values: DeepPartial<Values>) => void;
9494
setPreserve: (preserve: boolean) => void;
9595
setValidateMessages: (messages: ValidateMessages) => void;
9696
}

primitives/filed-form /src/Form.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,13 @@ import type { FormInstance, InternalFormContext, InternalFormInstance, RegisterC
88
import { FieldContextProvider } from './FieldContext';
99
import type { ValidateMessages } from './form-core/validate';
1010
import useForm from './useForm';
11+
import { DeepPartial } from 'skyroc-type-utils';
1112

1213
interface FormBaseProps<Values = any> extends RegisterCallbackOptions<Values> {
1314
children?: React.ReactNode;
1415
clearOnDestroy?: boolean;
1516
form?: FormInstance<Values>;
16-
initialValues?: Partial<Values>;
17+
initialValues?: DeepPartial<Values>;
1718
preserve?: boolean;
1819
validateMessages?: ValidateMessages;
1920
validateTrigger?: string | string[];

primitives/filed-form /src/createStore.ts

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -254,16 +254,18 @@ class FormStore {
254254
this._errors.clear();
255255
this._warnings.clear();
256256
this._validating.clear();
257-
this.enqueueNotify();
257+
this.enqueueNotify([], ChangeTag.Reset | ChangeTag.Value);
258258
return;
259259
}
260260

261261
const keys: string[] = [];
262+
263+
let resetValue: Store = {};
264+
262265
for (const n of names) {
263266
const key = keyOfName(n);
264267

265-
const initV = get(this._initial, key);
266-
this.updateStore(set(this._store, key, initV));
268+
resetValue = set(resetValue, key, get(this._initial, key));
267269

268270
this._touched.delete(key);
269271
this._dirty.delete(key);
@@ -272,7 +274,10 @@ class FormStore {
272274
this._validating.delete(key);
273275
keys.push(key);
274276
}
275-
this.enqueueNotify(keys);
277+
278+
this.updateStore(resetValue);
279+
280+
this.enqueueNotify(keys, ChangeTag.Reset | ChangeTag.Value);
276281
};
277282

278283
// ------------------------------------------------
@@ -1030,7 +1035,7 @@ class FormStore {
10301035
};
10311036

10321037
private enqueueNotify = (names?: NamePath[] | string[], mask: ChangeMask = ChangeTag.All) => {
1033-
if (!names) this.markPending('*', ChangeTag.All);
1038+
if (!names || names.length === 0) this.markPending('*', mask);
10341039
else for (const n of names) this.markPending(keyOfName(n), mask);
10351040

10361041
this.scheduleFlush();

primitives/filed-form /src/form-core/types.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// src/form-core/types.ts
22

33
import type { NamePath } from '../utils/util';
4+
import { ChangeMask } from './event';
45

56
export type Store = Record<string, any>;
67
export type StoreValue = any;
@@ -23,7 +24,7 @@ export interface Rule {
2324
}
2425

2526
export interface FieldEntity {
26-
changeValue: (value: any, isShouldUpdate: boolean) => void;
27+
changeValue: (value: StoreValue, key: string, all: Store, fired: ChangeMask) => void;
2728
initialValue?: any;
2829
name: NamePath;
2930
preserve?: boolean;

0 commit comments

Comments
 (0)