Skip to content

Commit 156fdd3

Browse files
committed
fix(Form): 内嵌组件 & 样式处理
1 parent f90f8ec commit 156fdd3

File tree

6 files changed

+181
-27
lines changed

6 files changed

+181
-27
lines changed

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

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,61 @@ const FormDemo = () => {
99
{
1010
type: 'input',
1111
field: 'name',
12+
name: '姓名',
13+
attr: {},
1214
validate: (val: any) => (!val ? `请输入name` : ''),
1315
},
1416
{
1517
type: 'input',
1618
field: 'age',
19+
name: '年龄',
1720
validate: (val: any) => (Number(val) > 30 || Number(val) < 10 ? `起输入10-30` : ''),
1821
},
22+
{
23+
type: 'radio',
24+
field: 'sex',
25+
name: '菜',
26+
options: [
27+
{label: '四川菜', value: 1},
28+
{label: '湖北菜', value: 2},
29+
{label: '西北菜', value: 3},
30+
{label: '新疆菜', value: 4},
31+
{label: '东北菜', value: 5},
32+
],
33+
},
34+
{
35+
type: 'checkBox',
36+
field: 'fruit',
37+
name: '水果',
38+
options: [
39+
{label: '香蕉', value: 1},
40+
{label: '西瓜', value: 2},
41+
{label: '猕猴桃', value: 3},
42+
],
43+
},
44+
{
45+
type: 'rate',
46+
field: 'rate',
47+
name: '评分',
48+
},
49+
{
50+
type: 'switch',
51+
field: 'switch',
52+
name: '开关',
53+
},
54+
{
55+
type: 'search',
56+
field: 'search',
57+
name: '搜索',
58+
options: [
59+
{label: '上海', value: 1},
60+
{label: '南京', value: 2},
61+
],
62+
attr: {
63+
labelInValue: true,
64+
showClear: true,
65+
},
66+
},
1967
];
2068
const initialValues = {name: '王滴滴', age: '31'};
2169

Lines changed: 121 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
1-
import React, { FC, useContext, useEffect } from 'react';
1+
import React, { FC, useContext } from 'react';
22
import { KeyType, FormItemsProps } from './types';
33
import { Context } from './hooks/context';
4-
import Input from '../Input';
5-
import { View, Text, TextInput } from 'react-native';
4+
import Radio from '../Radio';
5+
import CheckBox from '../CheckBox';
6+
import Rating from '../Rating';
7+
import Switch from '../Switch';
8+
import SearchBar from '../SearchBar';
9+
import { View, Text, SafeAreaView, StyleSheet, TextInput } from 'react-native';
610

711
const FormItems: FC<any> = ({ formDatas = [] }) => {
812
const {
@@ -16,28 +20,128 @@ const FormItems: FC<any> = ({ formDatas = [] }) => {
1620
forceUpdate();
1721
};
1822

23+
const _renderComponent = (v: FormItemsProps) => {
24+
const options = v.options || [];
25+
if (v.type === 'render') {
26+
return v.render;
27+
}
28+
if (v.type === 'input') {
29+
return (
30+
<TextInput
31+
value={store[v.field]}
32+
onChangeText={(value) => change(v.field, value)}
33+
onBlur={() => validate()}
34+
{...v.attr}
35+
/>
36+
);
37+
}
38+
if (v.type === 'radio') {
39+
return options.map((item, idx) => (
40+
<Radio
41+
key={idx}
42+
checked={item.value === store[v.field]}
43+
onPress={() => change(v.field, item.value)}
44+
{...v.attr}
45+
>
46+
{item.label}
47+
</Radio>
48+
));
49+
}
50+
if (v.type === 'checkBox') {
51+
return options.map((item, idx) => {
52+
const values = store[v.field] || [];
53+
return (
54+
<CheckBox
55+
key={idx}
56+
checked={values.includes(item.value)}
57+
onChange={() => {
58+
let data = store[v.field] || [];
59+
if (!data.includes(item.value)) {
60+
data.push(item.value);
61+
} else {
62+
const idx = data.findIndex((v: KeyType) => v === item.value);
63+
data.splice(idx, 1);
64+
}
65+
change(v.field, data);
66+
}}
67+
{...v.attr}
68+
>
69+
{item.label}
70+
</CheckBox>
71+
);
72+
});
73+
}
74+
if (v.type === 'rate') {
75+
return <Rating onPress={(number) => change(v.field, number)} {...v.attr} />;
76+
}
77+
if (v.type === 'switch') {
78+
return <Switch checked={store[v.field]} onValueChange={() => change(v.field, !store[v.field])} {...v.attr} />;
79+
}
80+
if (v.type === 'search') {
81+
return (
82+
<SearchBar
83+
options={options}
84+
onChange={(val) => change(v.field, val)}
85+
contentStyle={{ paddingHorizontal: 0 }}
86+
{...v.attr}
87+
/>
88+
);
89+
}
90+
return null;
91+
};
92+
93+
const Label = (v: FormItemsProps) => {
94+
return (
95+
<Text style={styles.label} {...v.attr}>
96+
{v.name}
97+
</Text>
98+
);
99+
};
100+
101+
const Tip = (v: FormItemsProps) => {
102+
const content = validator.message(v.field, store[v.field], {
103+
validate: v?.validate,
104+
});
105+
return <Text style={{ color: 'red', marginBottom: content && 10, marginTop: content && 10 }}>{content}</Text>;
106+
};
107+
19108
const _render = () => {
20109
return formDatas.map((v: FormItemsProps, i: number) => {
21-
let _render;
22-
if (v.type === 'input') {
23-
_render = (
24-
<Input value={store[v.field]} onChangeText={(value) => change(v.field, value)} onBlur={() => validate()} />
25-
);
26-
}
27110
return (
28-
<View key={i}>
29-
{_render}
30-
<Text style={{ color: 'red' }}>
31-
{validator.message(v.field, store[v.field], {
32-
validate: v?.validate,
33-
})}
34-
</Text>
111+
<View key={i} style={styles.form_items_container}>
112+
<View style={styles.form_items}>
113+
{Label(v)}
114+
{_renderComponent(v)}
115+
{Tip(v)}
116+
</View>
35117
</View>
36118
);
37119
});
38120
};
39121

40-
return <React.Fragment>{_render()}</React.Fragment>;
122+
return <SafeAreaView style={styles.warpper}>{_render()}</SafeAreaView>;
41123
};
42124

125+
const styles = StyleSheet.create({
126+
warpper: {
127+
backgroundColor: '#fff',
128+
},
129+
form_items_container: {
130+
flex: 1,
131+
},
132+
form_items: {
133+
textAlign: 'center',
134+
margin: 10,
135+
borderBottomWidth: 0.5,
136+
borderBottomColor: '#eee',
137+
},
138+
label: {
139+
width: 110,
140+
fontSize: 16,
141+
color: '#434343',
142+
fontWeight: '500',
143+
marginBottom: 10,
144+
},
145+
});
146+
43147
export default FormItems;

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

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -77,14 +77,8 @@ export default function useForm<
7777
});
7878
};
7979

80-
const getStore = (): Partial<FormData> => {
81-
const { store } = state;
82-
return store;
83-
};
84-
8580
const getFormInstance = () => {
8681
return {
87-
getStore,
8882
getFieldValue,
8983
setFieldValue,
9084
resetFieldValue,

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { RulesOption } from '@validator.tool/hook';
2+
import React from 'react';
23
import Validator from 'validator.tool';
34

45
type KeyType = string | number | symbol;
@@ -16,7 +17,6 @@ export type InnerMethodsReturnType<
1617
};
1718

1819
type FormInstance<FormData = any, FieldValue = FormData[keyof FormData], FieldKey extends KeyType = keyof FormData> = {
19-
getStore: () => FormData;
2020
getFieldValue: (field: FieldKey) => FieldValue;
2121
setFieldValue: (field: FieldKey, value: FieldValue) => void;
2222
resetFieldValue: () => void;
@@ -34,7 +34,11 @@ interface FormProps<FormData = any, FieldValue = FormData[keyof FormData], Field
3434
interface FormItemsProps {
3535
field: string;
3636
type: string;
37+
name: string;
3738
validate?: RulesOption['validate'];
39+
options?: Array<{ label: string; value: KeyType | any }>;
40+
attr?: any;
41+
render?: React.ReactNode;
3842
}
3943

4044
export type { FormProps, FormItemsProps, KeyType, FormInstance };

packages/core/src/SearchBar/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ function Demo() {
1717
{label:'上海',value:1},
1818
{label:'南京',value:2}
1919
]}
20-
onFocu={()=>{}}
20+
onFocus={()=>{}}
2121
onChange={val=>console.log('val',val)}
2222
/>
2323
);

packages/core/src/SearchBar/index.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import {
77
TouchableWithoutFeedback,
88
ActivityIndicator,
99
Pressable,
10+
StyleProp,
11+
ViewStyle,
1012
} from 'react-native';
1113
import MaskLayer from '../MaskLayer';
1214
import SearchInputBar from '../SearchInputBar';
@@ -27,6 +29,7 @@ interface SearchBarProps {
2729
placeholder?: String;
2830
extra?: JSX.Element;
2931
showClear?: boolean;
32+
contentStyle?: StyleProp<ViewStyle>;
3033
}
3134

3235
interface OptionsState {
@@ -48,6 +51,7 @@ function SearchBar({
4851
placeholder,
4952
extra,
5053
showClear = true,
54+
contentStyle = {},
5155
}: SearchBarProps) {
5256
const [curValue, setCurValue] = useState<any>(value);
5357
const [visible, setVisivble] = useState(false);
@@ -76,7 +80,7 @@ function SearchBar({
7680

7781
return !visible ? (
7882
<Pressable onPress={showSearchBar}>
79-
<View style={[styles.content]}>
83+
<View style={[styles.content, contentStyle]}>
8084
<Text style={styles.contentTitle}>{textValue ? textValue : placeholder}</Text>
8185
{React.isValidElement(extra) ? (
8286
extra
@@ -91,7 +95,7 @@ function SearchBar({
9195
<Icon name="circle-close-o" size={18} color="#ccc" />
9296
</Pressable>
9397
) : (
94-
<Icon xml={down} size={18} color="#A19EA0" />
98+
<Icon name="right" size={18} color="#A19EA0" />
9599
)}
96100
</View>
97101
</Pressable>

0 commit comments

Comments
 (0)