@simpleform/render 3.0.8 → 3.0.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +80 -41
- package/README_CN.md +81 -42
- package/lib/index.js +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
English | [中文说明](./README_CN.md)
|
|
4
4
|
|
|
5
|
-
[](https://www.npmjs.com/package/@simpleform/render)
|
|
6
6
|
|
|
7
7
|
> A lightweight dynamic forms engine that makes it easy to dynamically render forms.
|
|
8
8
|
|
|
@@ -307,65 +307,104 @@ export default function Demo(props) {
|
|
|
307
307
|
### 4. List Demo
|
|
308
308
|
Support for array rendering
|
|
309
309
|
```javascript
|
|
310
|
-
import React, { useState } from 'react';
|
|
311
|
-
import FormRender, { useSimpleForm } from './form-render';
|
|
310
|
+
import React, { useEffect, useState } from 'react';
|
|
311
|
+
import FormRender, { CustomFormRenderProps, useSimpleForm } from './form-render';
|
|
312
312
|
import { Button } from 'antd';
|
|
313
|
-
|
|
313
|
+
|
|
314
|
+
const OptionList = React.forwardRef<HTMLElement, any>((props, ref) => {
|
|
315
|
+
|
|
316
|
+
const {
|
|
317
|
+
value,
|
|
318
|
+
onChange,
|
|
319
|
+
...rest
|
|
320
|
+
} = props;
|
|
321
|
+
|
|
322
|
+
const intialValue = [{ label: '', value: '' }];
|
|
323
|
+
const [dataSource, setDataSource] = useState<Array<any>>([]);
|
|
314
324
|
const form = useSimpleForm();
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
+
|
|
326
|
+
useEffect(() => {
|
|
327
|
+
const options = value || [...intialValue];
|
|
328
|
+
setDataSource(options);
|
|
329
|
+
form.setFieldsValue(options);
|
|
330
|
+
}, [value]);
|
|
331
|
+
|
|
332
|
+
const widgetList = dataSource.map((item, index) => ({
|
|
333
|
+
type: 'row',
|
|
334
|
+
props: {
|
|
335
|
+
gutter: 12,
|
|
336
|
+
align: 'middle'
|
|
337
|
+
},
|
|
338
|
+
widgetList: [
|
|
325
339
|
{
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
340
|
+
name: `[${index}]label`,
|
|
341
|
+
compact: true,
|
|
342
|
+
outside: { type: 'col', props: { span: 9 } },
|
|
343
|
+
rules: [{ required: true }],
|
|
330
344
|
type: 'Input',
|
|
331
|
-
props: {
|
|
345
|
+
props: {
|
|
346
|
+
placeholder: 'label',
|
|
347
|
+
style: { width: '100%' }
|
|
348
|
+
}
|
|
332
349
|
},
|
|
333
350
|
{
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
351
|
+
name: `[${index}]value`,
|
|
352
|
+
compact: true,
|
|
353
|
+
outside: { type: 'col', props: { span: 9 } },
|
|
354
|
+
rules: [{ required: true }],
|
|
338
355
|
type: 'Input',
|
|
339
|
-
props: {
|
|
356
|
+
props: {
|
|
357
|
+
placeholder: 'value',
|
|
358
|
+
style: { width: '100%' }
|
|
359
|
+
}
|
|
340
360
|
},
|
|
341
361
|
{
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
rules: [{ required: true, message: 'list[3] empty' }],
|
|
345
|
-
initialValue: 4,
|
|
346
|
-
type: 'Input',
|
|
347
|
-
props: {}
|
|
362
|
+
outside: { type: 'col', props: { span: 6 } },
|
|
363
|
+
typeRender: <Button type="link" onClick={() => deleteItem(index)}>delete</Button>
|
|
348
364
|
},
|
|
349
|
-
]
|
|
365
|
+
]
|
|
366
|
+
}));
|
|
367
|
+
|
|
368
|
+
const deleteItem = (index: number) => {
|
|
369
|
+
const oldData = [...dataSource];
|
|
370
|
+
if (!oldData) return;
|
|
371
|
+
const newData = [...oldData];
|
|
372
|
+
newData.splice(index, 1);
|
|
373
|
+
setDataSource(newData);
|
|
374
|
+
form.setFieldsValue(newData);
|
|
375
|
+
onChange && onChange(newData);
|
|
376
|
+
};
|
|
350
377
|
|
|
351
|
-
const
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
378
|
+
const addItem = () => {
|
|
379
|
+
const { error } = await form.validate();
|
|
380
|
+
if (error) {
|
|
381
|
+
return;
|
|
382
|
+
}
|
|
383
|
+
const newData = dataSource.concat(intialValue);
|
|
384
|
+
form.setFieldsValue(newData);
|
|
385
|
+
setDataSource(newData);
|
|
386
|
+
};
|
|
387
|
+
|
|
388
|
+
const onFieldsChange: CustomFormRenderProps['onFieldsChange'] = (_, values) => {
|
|
389
|
+
setDataSource(values);
|
|
390
|
+
onChange && onChange(values);
|
|
355
391
|
};
|
|
356
392
|
|
|
357
393
|
return (
|
|
358
|
-
<div
|
|
394
|
+
<div>
|
|
359
395
|
<FormRender
|
|
360
396
|
form={form}
|
|
361
397
|
widgetList={widgetList}
|
|
398
|
+
onFieldsChange={onFieldsChange}
|
|
362
399
|
/>
|
|
363
|
-
<
|
|
364
|
-
|
|
365
|
-
</
|
|
400
|
+
<Button type="link" onClick={addItem}>
|
|
401
|
+
add
|
|
402
|
+
</Button>
|
|
366
403
|
</div>
|
|
367
404
|
);
|
|
368
|
-
}
|
|
405
|
+
});
|
|
406
|
+
|
|
407
|
+
export default OptionList;
|
|
369
408
|
```
|
|
370
409
|
## API
|
|
371
410
|
|
|
@@ -400,7 +439,7 @@ Sourced from [@simpleform/form](../form);
|
|
|
400
439
|
## Other
|
|
401
440
|
|
|
402
441
|
### widgetList structure description
|
|
403
|
-
Each item in the `widgetList` list is a rendering node, divided into a form control node and nonform node.
|
|
442
|
+
Each item in the `widgetList` list is a rendering node, rendered from `type` and `props`. divided into a form control node and nonform node.
|
|
404
443
|
- Form control nodes.
|
|
405
444
|
Nodes with the `name` attribute are form control nodes and carry the form field component (`Form.Item`) by default, for example:
|
|
406
445
|
```javascript
|
package/README_CN.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
[English](./README.md) | 中文说明
|
|
4
4
|
|
|
5
|
-
[](https://www.npmjs.com/package/@simpleform/render)
|
|
6
6
|
|
|
7
7
|
> 轻量级动态表单引擎,实现动态渲染表单很简单.
|
|
8
8
|
|
|
@@ -308,67 +308,106 @@ export default function Demo(props) {
|
|
|
308
308
|
}
|
|
309
309
|
```
|
|
310
310
|
### 4. 数组数据
|
|
311
|
-
|
|
311
|
+
复杂的列表渲染增删改功能demo
|
|
312
312
|
```javascript
|
|
313
|
-
import React, { useState } from 'react';
|
|
314
|
-
import FormRender, { useSimpleForm } from './form-render';
|
|
313
|
+
import React, { useEffect, useState } from 'react';
|
|
314
|
+
import FormRender, { CustomFormRenderProps, useSimpleForm } from './form-render';
|
|
315
315
|
import { Button } from 'antd';
|
|
316
|
-
|
|
316
|
+
|
|
317
|
+
const OptionList = React.forwardRef<HTMLElement, any>((props, ref) => {
|
|
318
|
+
|
|
319
|
+
const {
|
|
320
|
+
value,
|
|
321
|
+
onChange,
|
|
322
|
+
...rest
|
|
323
|
+
} = props;
|
|
324
|
+
|
|
325
|
+
const intialValue = [{ label: '', value: '' }];
|
|
326
|
+
const [dataSource, setDataSource] = useState<Array<any>>([]);
|
|
317
327
|
const form = useSimpleForm();
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
+
|
|
329
|
+
useEffect(() => {
|
|
330
|
+
const options = value || [...intialValue];
|
|
331
|
+
setDataSource(options);
|
|
332
|
+
form.setFieldsValue(options);
|
|
333
|
+
}, [value]);
|
|
334
|
+
|
|
335
|
+
const widgetList = dataSource.map((item, index) => ({
|
|
336
|
+
type: 'row',
|
|
337
|
+
props: {
|
|
338
|
+
gutter: 12,
|
|
339
|
+
align: 'middle',
|
|
340
|
+
},
|
|
341
|
+
widgetList: [
|
|
328
342
|
{
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
343
|
+
name: `[${index}]label`,
|
|
344
|
+
compact: true,
|
|
345
|
+
outside: { type: 'col', props: { span: 9 } },
|
|
346
|
+
rules: [{ required: true }],
|
|
333
347
|
type: 'Input',
|
|
334
|
-
props: {
|
|
348
|
+
props: {
|
|
349
|
+
placeholder: 'label',
|
|
350
|
+
style: { width: '100%' }
|
|
351
|
+
}
|
|
335
352
|
},
|
|
336
353
|
{
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
354
|
+
name: `[${index}]value`,
|
|
355
|
+
compact: true,
|
|
356
|
+
outside: { type: 'col', props: { span: 9 } },
|
|
357
|
+
rules: [{ required: true }],
|
|
341
358
|
type: 'Input',
|
|
342
|
-
props: {
|
|
359
|
+
props: {
|
|
360
|
+
placeholder: 'value',
|
|
361
|
+
style: { width: '100%' }
|
|
362
|
+
}
|
|
343
363
|
},
|
|
344
364
|
{
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
rules: [{ required: true, message: 'list[3] empty' }],
|
|
348
|
-
initialValue: 4,
|
|
349
|
-
type: 'Input',
|
|
350
|
-
props: {}
|
|
365
|
+
outside: { type: 'col', props: { span: 6 } },
|
|
366
|
+
typeRender: <Button type="link" onClick={() => deleteItem(index)}>delete</Button>
|
|
351
367
|
},
|
|
352
|
-
]
|
|
368
|
+
]
|
|
369
|
+
}));
|
|
370
|
+
|
|
371
|
+
const deleteItem = (index: number) => {
|
|
372
|
+
const oldData = [...dataSource];
|
|
373
|
+
if (!oldData) return;
|
|
374
|
+
const newData = [...oldData];
|
|
375
|
+
newData.splice(index, 1);
|
|
376
|
+
setDataSource(newData);
|
|
377
|
+
form.setFieldsValue(newData);
|
|
378
|
+
onChange && onChange(newData);
|
|
379
|
+
};
|
|
353
380
|
|
|
354
|
-
const
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
381
|
+
const addItem = () => {
|
|
382
|
+
const { error } = await form.validate();
|
|
383
|
+
if (error) {
|
|
384
|
+
return;
|
|
385
|
+
}
|
|
386
|
+
const newData = dataSource.concat(intialValue);
|
|
387
|
+
form.setFieldsValue(newData);
|
|
388
|
+
setDataSource(newData);
|
|
389
|
+
};
|
|
390
|
+
|
|
391
|
+
const onFieldsChange: CustomFormRenderProps['onFieldsChange'] = (_, values) => {
|
|
392
|
+
setDataSource(values);
|
|
393
|
+
onChange && onChange(values);
|
|
358
394
|
};
|
|
359
395
|
|
|
360
396
|
return (
|
|
361
|
-
<div
|
|
397
|
+
<div>
|
|
362
398
|
<FormRender
|
|
363
399
|
form={form}
|
|
364
400
|
widgetList={widgetList}
|
|
401
|
+
onFieldsChange={onFieldsChange}
|
|
365
402
|
/>
|
|
366
|
-
<
|
|
367
|
-
|
|
368
|
-
</
|
|
403
|
+
<Button type="link" onClick={addItem}>
|
|
404
|
+
add
|
|
405
|
+
</Button>
|
|
369
406
|
</div>
|
|
370
407
|
);
|
|
371
|
-
}
|
|
408
|
+
});
|
|
409
|
+
|
|
410
|
+
export default OptionList;
|
|
372
411
|
```
|
|
373
412
|
|
|
374
413
|
## API
|
|
@@ -404,7 +443,7 @@ export default function Demo(props) {
|
|
|
404
443
|
## 其他
|
|
405
444
|
|
|
406
445
|
### widgetList结构说明
|
|
407
|
-
`widgetList`列表中每一项均为一个渲染节点, 分为表单控件节点和非控件节点
|
|
446
|
+
`widgetList`列表中每一项均为一个渲染节点, 由`type`和`props`渲染而成, 分为表单控件节点和非控件节点
|
|
408
447
|
- 表单控件节点:
|
|
409
448
|
具有`name`属性的节点为表单控件节点,默认携带表单域组件(`Form.Item`),举例:
|
|
410
449
|
```javascript
|