Skip to content

Commit 1081137

Browse files
committed
feat(Form): 动态列表增加头部和新增api
1 parent 16a9436 commit 1081137

File tree

10 files changed

+183
-100
lines changed

10 files changed

+183
-100
lines changed

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

Lines changed: 38 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,15 @@ const FormDemo = () => {
88
const form = Form.useForm({
99
changeValidate: true,
1010
watch: {
11-
name: (value: unknown) => {
12-
console.log('value', value);
13-
},
11+
name: (value: unknown) => console.log('value', value),
1412
},
1513
customComponentList: {
1614
render: <Slider />,
1715
},
1816
});
1917
const [state, setStore] = useState({});
20-
const items = [
18+
19+
const schema = [
2120
{
2221
type: 'input',
2322
field: 'name',
@@ -36,6 +35,11 @@ const FormDemo = () => {
3635
{label: '西北菜', value: 3},
3736
{label: '新疆菜', value: 4},
3837
{label: '东北菜', value: 5},
38+
{label: '四川菜', value: 6},
39+
{label: '湖北菜', value: 7},
40+
{label: '西北菜', value: 8},
41+
{label: '新疆菜', value: 9},
42+
{label: '东北菜', value: 10},
3943
],
4044
},
4145
{
@@ -46,12 +50,22 @@ const FormDemo = () => {
4650
{label: '香蕉', value: 1},
4751
{label: '西瓜', value: 2},
4852
{label: '猕猴桃', value: 3},
53+
{label: '新疆菜', value: 4},
54+
{label: '东北菜', value: 5},
55+
{label: '四川菜', value: 6},
56+
{label: '湖北菜', value: 7},
57+
{label: '西北菜', value: 8},
58+
{label: '新疆菜', value: 9},
59+
{label: '东北菜', value: 10},
4960
],
5061
},
5162
{
5263
type: 'rate',
5364
field: 'rate',
5465
name: '评分',
66+
attr: {
67+
defaultRating: 4,
68+
},
5569
},
5670
{
5771
type: 'switch',
@@ -71,12 +85,6 @@ const FormDemo = () => {
7185
showClear: true,
7286
},
7387
},
74-
{
75-
type: 'datePicker',
76-
field: 'datePicker',
77-
name: '时间',
78-
attr: {},
79-
},
8088
{
8189
type: 'stepper',
8290
field: 'stepper',
@@ -110,23 +118,39 @@ const FormDemo = () => {
110118
{
111119
type: 'cardList',
112120
field: 'cardList',
113-
name: '动态list',
121+
name: '联系人集合',
122+
renderHeader: (i: number, {remove}: {remove: () => void}) => (
123+
<View style={{marginTop: 12, display: 'flex', justifyContent: 'space-between', flexDirection: 'row'}}>
124+
<View>
125+
<Text>{`联系人${i + 1}`}</Text>
126+
</View>
127+
<View>
128+
<Text onPress={() => remove()}>删除</Text>
129+
</View>
130+
</View>
131+
),
132+
renderAdd: ({add}: {add: () => void}) => (
133+
<View style={{marginTop: 12}}>
134+
<Button onPress={() => add()} type="primary" size="default" bordered={false}>
135+
新增数据
136+
</Button>
137+
</View>
138+
),
114139
items: [
115140
{
116141
type: 'input',
117142
field: 'cardListItem1',
118-
name: '动态表单项1',
143+
name: '联系人姓名',
119144
},
120145
],
121146
},
122147
];
123-
const initialValues = {name: '王滴滴', rate: 4};
124148

125149
return (
126150
<Container>
127151
<Layout>
128152
<Body>
129-
<Form form={form} formDatas={items} initialValues={initialValues} />
153+
<Form form={form} schema={schema} initialValues={{name: '王滴滴', rate: 4}} />
130154
<View>
131155
<Text>{JSON.stringify(state)}</Text>
132156
</View>

packages/core/src/Form/README.md

Lines changed: 67 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ const FormDemo = () => {
2222
];
2323
return (
2424
<SafeAreaView>
25-
<Form form={form} formDatas={items} initialValues={initialValues} />
25+
<Form form={form} schema={items} initialValues={initialValues} />
2626
</SafeAreaView>
2727
);
2828
}
@@ -53,7 +53,7 @@ const FormDemo = () => {
5353
];
5454
return (
5555
<SafeAreaView>
56-
<Form form={form} formDatas={items} initialValues={initialValues} />
56+
<Form form={form} schema={items} initialValues={initialValues} />
5757
<Button
5858
type="primary"
5959
onPress={() => {
@@ -100,7 +100,7 @@ const FormDemo = () => {
100100
];
101101
return (
102102
<SafeAreaView>
103-
<Form form={form} formDatas={items} initialValues={initialValues} />
103+
<Form form={form} schema={items} initialValues={initialValues} />
104104
</SafeAreaView>
105105
);
106106
};
@@ -134,47 +134,60 @@ const FormDemo = () => {
134134
];
135135
return (
136136
<SafeAreaView>
137-
<Form form={form} formDatas={items} initialValues={initialValues} />
137+
<Form form={form} schema={items} initialValues={initialValues} />
138138
</SafeAreaView>
139139
);
140140
};
141141
```
142142
<!--End-->
143143

144-
### 动态表单list
144+
### 动态添加表单list(当type为cardList时)
145145

146-
> ⚠️ 警告:目前仅能嵌套一层cardList<!--rehype:style=background: #F08800; color: #fff;-->
146+
> ⚠️ 警告:
147+
1.目前仅能嵌套一层cardList
148+
2.我们暂时无法验证到添加的表单项里的每一个字段<!--rehype:style=background: #F08800; color: #fff;-->
147149
<!--rehype:style=border-left: 8px solid #ffe564;background-color: #ffe56440;padding: 12px 16px;-->
148150

149151
<!--DemoStart-->
150152
```jsx
151-
import { SafeAreaView,Toast } from 'react-native';
152-
import { Form } from '@uiw/react-native';
153+
import { SafeAreaView,View,Text } from 'react-native';
154+
import { Form,Button } from '@uiw/react-native';
153155

154156
const FormDemo = () => {
155157
const form = Form.useForm({
156158
changeValidate: true,
157159
});
158160
const initialValues = {name: ''};
159161
const items = [
160-
{
162+
{
161163
type: 'cardList',
162164
field: 'cardList',
163-
name: '动态list',
164-
required: true,
165-
items:[
165+
name: '联系人集合',
166+
renderHeader: (i: number, { remove }: { remove: () => void }) => (
167+
<View style={{ marginTop: 12, display: 'flex', justifyContent: 'space-between', flexDirection: 'row' }}>
168+
<View><Text>{`联系人${i + 1}`}</Text></View>
169+
<View><Text onPress={() => remove()}>删除</Text></View>
170+
</View>
171+
),
172+
renderAdd: ({ add }: { add: () => void }) => (
173+
<View style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', marginTop: 12 }}>
174+
<Button onPress={() => add()} type="primary" size="default">
175+
新增数据
176+
</Button>
177+
</View>
178+
),
179+
items: [
166180
{
167181
type: 'input',
168-
field: 'cardList',
169-
name: '动态list',
170-
required: true,
171-
}
172-
]
173-
}
182+
field: 'cardListItem1',
183+
name: '联系人姓名',
184+
},
185+
],
186+
},
174187
];
175188
return (
176189
<SafeAreaView>
177-
<Form form={form} formDatas={items} initialValues={initialValues} />
190+
<Form form={form} schema={items} initialValues={initialValues} />
178191
</SafeAreaView>
179192
);
180193
};
@@ -187,39 +200,71 @@ interface FormProps<FormData = any, FieldValue = FormData[keyof FormData], Field
187200
/**
188201
* 表单集合
189202
*/
190-
formDatas?: FormItemsProps[];
203+
schema?: FormItemsProps[];
191204
/**
192-
* useForm表单实例
205+
* 经 Form.useForm() 创建的 form 控制实例,不提供时会自动创建
193206
*/
194207
form: FormInstance<FormData, FieldValue, FieldKey>;
195208
/**
196-
* 表单默认值
209+
* 表单默认值,只有初始化以及重置时生效
197210
*/
198211
initialValues?: Partial<FormData>;
212+
/**
213+
* 支持默认和卡片两种模式
214+
*/
215+
mode?:'default' | 'card'
199216
}
200217
```
201218

202219
### FormItemsProps
203220
```ts
204221
interface FormItemsProps {
222+
// 字段名
205223
field: string;
224+
// 字段类型(默认继承了react-native-uiw中的 input | textArea | slider | rate | radio | search | switch | checkBox | stepper | cardList )
206225
type: string;
226+
// 标签名
207227
name: string;
228+
// 验证规则
208229
validate?: RulesOption['validate'];
209230
options?: Array<{ label: string; value: KeyType | any }>;
231+
// 表单控件props
210232
attr?: any;
233+
// 展示是否必填
211234
required?: boolean;
235+
// 是否隐藏
212236
hide?:boolean
237+
// 当type为cardList生效,渲染每一项的头部内容
238+
renderHeader?:(index:number,{ remove }:{ remove:()=>void })=>React.ReactNode;
239+
// 当type为cardList生效,渲染添加按钮的文案
240+
renderAdd?:( { add }:{ add:()=>void } )=>React.ReactNode;
241+
// 当type为cardList生效,配置表单项
242+
items?: Omit<FormItemsProps, 'validate' | 'required'>[];
213243
}
214244
```
215245

216246
### FormInstance
217247
```ts
218248
type FormInstance<FormData = any, FieldValue = FormData[keyof FormData], FieldKey extends KeyType = keyof FormData> = {
249+
/**
250+
* 获取对应字段名的值
251+
*/
219252
getFieldValue: (field: FieldKey) => FieldValue;
253+
/**
254+
* 设置对应字段名的值
255+
*/
220256
setFieldValue: (field: FieldKey, value: FieldValue) => void;
257+
/**
258+
* 重制表单
259+
*/
221260
resetFieldValue: () => void;
261+
/**
262+
* 触发验证
263+
*/
222264
validate: () => Partial<Record<string, string>>;
265+
/**
266+
* 触发表单验证获取表单数据
267+
*/
223268
validateFields: () => Promise<FormData> | any;
224269
getInnerMethods: (inner?: boolean) => InnerMethodsReturnType<FormData>;
225270
};

packages/core/src/Form/comps/checkBox.tsx

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import React from 'react';
2+
import { View } from 'react-native';
23
import { KeyType } from '../types';
34
import CheckBox, { CheckBoxProps } from '../../CheckBox';
5+
import Flex from '../../Flex';
46

57
interface FormCheckBoxProps extends CheckBoxProps {
68
value?: KeyType[];
@@ -10,9 +12,9 @@ interface FormCheckBoxProps extends CheckBoxProps {
1012

1113
const FormCheckBox = ({ value = [], onChange, options = [], ...others }: FormCheckBoxProps) => {
1214
return (
13-
<React.Fragment>
14-
{options.map((item, idx) => {
15-
return (
15+
<Flex justify="start" wrap="wrap" style={{ paddingTop: 15 }}>
16+
{options.map((item, idx) => (
17+
<View key={idx} style={{ marginRight: 15, marginBottom: 15, height: 24 }}>
1618
<CheckBox
1719
key={idx}
1820
checked={value.includes(item.value)}
@@ -30,9 +32,9 @@ const FormCheckBox = ({ value = [], onChange, options = [], ...others }: FormChe
3032
>
3133
{item.label}
3234
</CheckBox>
33-
);
34-
})}
35-
</React.Fragment>
35+
</View>
36+
))}
37+
</Flex>
3638
);
3739
};
3840

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import React from 'react';
2+
import Card from '../../Card';
3+
import { SafeAreaView } from 'react-native';
4+
import styles from '../styles';
5+
6+
const Container = ({ mode, children }: { mode: 'card' | 'default'; children?: JSX.Element }) => {
7+
return mode === 'card' ? <Card>{children}</Card> : <SafeAreaView style={styles.warpper}>{children}</SafeAreaView>;
8+
};
9+
10+
export default Container;

packages/core/src/Form/comps/radio.tsx

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import React from 'react';
2+
import { View } from 'react-native';
23
import { KeyType } from '../types';
34
import Radio, { RadioProps } from '../../Radio';
5+
import Flex from '../../Flex';
46

57
interface FormRadioProps extends RadioProps {
68
value?: KeyType;
@@ -11,18 +13,21 @@ interface FormRadioProps extends RadioProps {
1113
const FormRadio = ({ value, onChange, options = [], ...others }: FormRadioProps) => {
1214
return (
1315
<React.Fragment>
14-
{options.map((item, idx) => (
15-
<Radio
16-
key={idx}
17-
checked={item.value === value}
18-
onPress={() => {
19-
onChange?.(item.value);
20-
}}
21-
{...others}
22-
>
23-
{item.label}
24-
</Radio>
25-
))}
16+
<Flex justify="start" wrap="wrap" style={{ paddingTop: 15 }}>
17+
{options.map((item, idx) => (
18+
<View key={idx} style={{ marginRight: 15, marginBottom: 15 }}>
19+
<Radio
20+
checked={item.value === value}
21+
onPress={() => {
22+
onChange?.(item.value);
23+
}}
24+
{...others}
25+
>
26+
{item.label}
27+
</Radio>
28+
</View>
29+
))}
30+
</Flex>
2631
</React.Fragment>
2732
);
2833
};

0 commit comments

Comments
 (0)