Skip to content

Commit 02670a1

Browse files
committed
fix(Form): 集成uiw表单控件
1 parent 3438477 commit 02670a1

File tree

5 files changed

+138
-38
lines changed

5 files changed

+138
-38
lines changed

example/examples/src/routes/Form/index.tsx

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,25 +4,22 @@ import Layout, {Container} from '../../Layout';
44
const {Body, Footer} = Layout;
55

66
const FormDemo = () => {
7-
const form = Form.useForm();
7+
const form = Form.useForm({
8+
changeValidate: true,
9+
});
810
const items = [
911
{
1012
type: 'input',
1113
field: 'name',
12-
name: '姓名',
14+
name: '输入框',
1315
attr: {},
16+
required: true,
1417
validate: (val: any) => (!val ? `请输入name` : ''),
1518
},
16-
{
17-
type: 'input',
18-
field: 'age',
19-
name: '年龄',
20-
validate: (val: any) => (Number(val) > 30 || Number(val) < 10 ? `起输入10-30` : ''),
21-
},
2219
{
2320
type: 'radio',
2421
field: 'sex',
25-
name: '',
22+
name: '单选框',
2623
options: [
2724
{label: '四川菜', value: 1},
2825
{label: '湖北菜', value: 2},
@@ -34,7 +31,7 @@ const FormDemo = () => {
3431
{
3532
type: 'checkBox',
3633
field: 'fruit',
37-
name: '水果',
34+
name: '多选框',
3835
options: [
3936
{label: '香蕉', value: 1},
4037
{label: '西瓜', value: 2},
@@ -70,8 +67,33 @@ const FormDemo = () => {
7067
name: '时间',
7168
attr: {},
7269
},
70+
{
71+
type: 'stepper',
72+
field: 'stepper',
73+
name: '步进器',
74+
attr: {
75+
size: 'small',
76+
},
77+
},
78+
{
79+
type: 'textArea',
80+
field: 'textArea',
81+
name: '多行输入框',
82+
attr: {
83+
showWords: true,
84+
maxLength: 100,
85+
},
86+
},
87+
{
88+
type: 'slider',
89+
field: 'slider',
90+
name: '滑块输入条',
91+
attr: {
92+
step: 0.2,
93+
},
94+
},
7395
];
74-
const initialValues = {name: '王滴滴', age: '31'};
96+
const initialValues = {name: '王滴滴'};
7597

7698
return (
7799
<Container>

packages/core/src/Form/formItems.tsx

Lines changed: 88 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,19 @@ import Rating from '../Rating';
77
import Switch from '../Switch';
88
import SearchBar from '../SearchBar';
99
import FormDatePicker from './comps/datePicker';
10+
import Stepper from '../Stepper';
11+
import TextArea from '../TextArea';
12+
import Slider from '../Slider';
13+
import Flex from '../Flex';
1014
import { View, Text, SafeAreaView, StyleSheet, TextInput } from 'react-native';
1115

1216
const FormItems: FC<any> = ({ formDatas = [] }) => {
1317
const {
14-
innerMethods: { store = {}, updateStore, forceUpdate, validator },
18+
innerMethods: { store = {}, updateStore, validator, innerValidate },
1519
} = useContext(Context);
1620

1721
const change = (field: KeyType, value: any) => updateStore?.({ store: { ...store, [field]: value } });
1822

19-
const validate = () => {
20-
validator.showMessages();
21-
forceUpdate();
22-
};
23-
2423
const _renderComponent = (v: FormItemsProps) => {
2524
const options = v.options || [];
2625
if (v.type === 'render') {
@@ -30,8 +29,24 @@ const FormItems: FC<any> = ({ formDatas = [] }) => {
3029
return (
3130
<TextInput
3231
value={store[v.field]}
33-
onChangeText={(value) => change(v.field, value)}
34-
onBlur={() => validate()}
32+
onChangeText={(value) => {
33+
change(v.field, value);
34+
v?.attr?.onChangeText?.(value);
35+
innerValidate();
36+
}}
37+
{...v.attr}
38+
/>
39+
);
40+
}
41+
if (v.type === 'textArea') {
42+
return (
43+
<TextArea
44+
onChange={(value: string) => {
45+
change(v.field, value);
46+
v?.attr?.onChange?.(value);
47+
innerValidate();
48+
}}
49+
value={store[v.field]}
3550
{...v.attr}
3651
/>
3752
);
@@ -41,7 +56,11 @@ const FormItems: FC<any> = ({ formDatas = [] }) => {
4156
<Radio
4257
key={idx}
4358
checked={item.value === store[v.field]}
44-
onPress={() => change(v.field, item.value)}
59+
onPress={() => {
60+
change(v.field, item.value);
61+
v?.attr?.onPress?.(item.value);
62+
innerValidate();
63+
}}
4564
{...v.attr}
4665
>
4766
{item.label}
@@ -64,8 +83,9 @@ const FormItems: FC<any> = ({ formDatas = [] }) => {
6483
data.splice(idx, 1);
6584
}
6685
change(v.field, data);
86+
v?.attr?.onChange?.(data);
87+
innerValidate();
6788
}}
68-
onBlur={() => validate()}
6989
{...v.attr}
7090
>
7191
{item.label}
@@ -74,17 +94,39 @@ const FormItems: FC<any> = ({ formDatas = [] }) => {
7494
});
7595
}
7696
if (v.type === 'rate') {
77-
return <Rating onPress={(number) => change(v.field, number)} {...v.attr} />;
97+
return (
98+
<Rating
99+
onPress={(number) => {
100+
change(v.field, number);
101+
v?.attr?.onPress?.(number);
102+
innerValidate();
103+
}}
104+
{...v.attr}
105+
/>
106+
);
78107
}
79108
if (v.type === 'switch') {
80-
return <Switch checked={store[v.field]} onValueChange={() => change(v.field, !store[v.field])} {...v.attr} />;
109+
return (
110+
<Switch
111+
checked={store[v.field]}
112+
onValueChange={(value) => {
113+
change(v.field, !store[v.field]);
114+
v?.attr?.onValueChange?.(value);
115+
innerValidate();
116+
}}
117+
{...v.attr}
118+
/>
119+
);
81120
}
82121
if (v.type === 'search') {
83122
return (
84123
<SearchBar
85124
options={options}
86-
onChange={(val) => change(v.field, val)}
87-
onBlur={() => validate()}
125+
onChange={(value) => {
126+
change(v.field, value);
127+
v?.attr?.onChange?.(value);
128+
innerValidate();
129+
}}
88130
contentStyle={{ paddingHorizontal: 0 }}
89131
{...v.attr}
90132
/>
@@ -93,14 +135,43 @@ const FormItems: FC<any> = ({ formDatas = [] }) => {
93135
if (v.type === 'datePicker') {
94136
return <FormDatePicker value={store[v.field]} ok={(value) => change(v.field, value)} {...v.attr} />;
95137
}
138+
if (v.type === 'stepper') {
139+
return (
140+
<Stepper
141+
value={store[v.field]}
142+
onChange={(value) => {
143+
change(v.field, value);
144+
v?.attr?.onChange?.(value);
145+
innerValidate();
146+
}}
147+
{...v.attr}
148+
/>
149+
);
150+
}
151+
if (v.type === 'slider') {
152+
return (
153+
<Slider
154+
value={store[v.field]}
155+
onChange={(value) => {
156+
change(v.field, value);
157+
v?.attr?.onChange?.(value);
158+
innerValidate();
159+
}}
160+
{...v.attr}
161+
/>
162+
);
163+
}
96164
return null;
97165
};
98166

99167
const Label = (v: FormItemsProps) => {
100168
return (
101-
<Text style={styles.label} {...v.attr}>
102-
{v.name}
103-
</Text>
169+
<Flex>
170+
{v.required && <Text style={{ color: 'red', marginRight: 5 }}>*</Text>}
171+
<Text style={styles.label} {...v.attr}>
172+
{v.name}
173+
</Text>
174+
</Flex>
104175
);
105176
};
106177

packages/core/src/Form/hooks/useForm.ts

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { KeyType, InnerMethodsReturnType } from '../types';
1+
import { KeyType, InnerMethodsReturnType, FormInstance } from '../types';
22
import { useState } from 'react';
33
import { useValidator } from '@validator.tool/hook';
44
import { isObjectEmpty } from '../utils/is';
@@ -13,7 +13,7 @@ export default function useForm<
1313
FormData = any,
1414
FieldValue = FormData[keyof FormData],
1515
FieldKey extends KeyType = keyof FormData,
16-
>(): any {
16+
>({ changeValidate = false }: { changeValidate?: boolean }): FormInstance<FormData, FieldValue, FieldKey> {
1717
const [state, setState] = useState<State>({
1818
initialValues: {},
1919
store: {},
@@ -30,6 +30,14 @@ export default function useForm<
3030
});
3131
};
3232

33+
const innerValidate = () => {
34+
const { showMessages } = validator;
35+
if (changeValidate) {
36+
showMessages?.();
37+
forceUpdate?.();
38+
}
39+
};
40+
3341
// 获取表单字段的值
3442
const getFieldValue = (field: FieldKey): FieldValue => {
3543
const { store } = state;
@@ -84,7 +92,7 @@ export default function useForm<
8492
resetFieldValue,
8593
validate,
8694
validateFields,
87-
getInnerMethods: (inner?: boolean): InnerMethodsReturnType<FormData, FieldValue, FieldKey> => {
95+
getInnerMethods: (inner?: boolean): InnerMethodsReturnType<FormData> => {
8896
let methods = {} as any;
8997
if (inner) {
9098
methods = {
@@ -93,6 +101,7 @@ export default function useForm<
93101
updateStore: updateStore,
94102
validator,
95103
forceUpdate,
104+
innerValidate,
96105
};
97106
}
98107
return methods;

packages/core/src/Form/types/index.tsx

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,13 @@ import Validator from 'validator.tool';
44

55
type KeyType = string | number | symbol;
66

7-
export type InnerMethodsReturnType<
8-
FormData = any,
9-
FieldValue = FormData[keyof FormData],
10-
FieldKey extends KeyType = keyof FormData,
11-
> = {
7+
export type InnerMethodsReturnType<FormData = any> = {
128
store: Partial<FormData>;
139
initialValues: Partial<FormData>;
1410
updateStore: (value: any) => void;
1511
validator: Validator;
1612
forceUpdate: () => void;
13+
innerValidate: () => void;
1714
};
1815

1916
type FormInstance<FormData = any, FieldValue = FormData[keyof FormData], FieldKey extends KeyType = keyof FormData> = {
@@ -22,7 +19,7 @@ type FormInstance<FormData = any, FieldValue = FormData[keyof FormData], FieldKe
2219
resetFieldValue: () => void;
2320
validate: () => Partial<Record<string, string>>;
2421
validateFields: () => Promise<FormData> | any;
25-
getInnerMethods: (inner?: boolean) => InnerMethodsReturnType<FormData, FieldValue, FieldKey>;
22+
getInnerMethods: (inner?: boolean) => InnerMethodsReturnType<FormData>;
2623
};
2724

2825
interface FormProps<FormData = any, FieldValue = FormData[keyof FormData], FieldKey extends KeyType = keyof FormData> {
@@ -38,6 +35,7 @@ interface FormItemsProps {
3835
validate?: RulesOption['validate'];
3936
options?: Array<{ label: string; value: KeyType | any }>;
4037
attr?: any;
38+
required?: boolean;
4139
render?: React.ReactNode;
4240
}
4341

packages/core/src/Stepper/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ function Stepper(props: StepProps) {
118118
onChange(valueRef.current);
119119
};
120120
return (
121-
<View style={[ControlStyle.elementCenter]}>
121+
<View style={[ControlStyle.elementCenter, { justifyContent: 'flex-start' }]}>
122122
<ControlValue
123123
size={size}
124124
delayLong={delayLong}

0 commit comments

Comments
 (0)