@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 CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  English | [中文说明](./README_CN.md)
4
4
 
5
- [![](https://img.shields.io/badge/version-3.0.8-green)](https://www.npmjs.com/package/@simpleform/render)
5
+ [![](https://img.shields.io/badge/version-3.0.10-green)](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
- export default function Demo(props) {
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
- const widgetList =
316
- [
317
- {
318
- label: "list-0",
319
- name: 'list[0]',
320
- rules: [{ required: true, message: 'list[0] empty' }],
321
- initialValue: 1,
322
- type: 'Input',
323
- props: {}
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
- label: "list-1",
327
- name: 'list[1]',
328
- rules: [{ required: true, message: 'list[1] empty' }],
329
- initialValue: 2,
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
- label: "list-2",
335
- name: 'list[2]',
336
- rules: [{ required: true, message: 'list[2] empty' }],
337
- initialValue: 3,
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
- label: "list-3",
343
- name: 'list[3]',
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 onSubmit = async (e) => {
352
- e?.preventDefault?.();
353
- const result = await form.validate();
354
- console.log(result, 'result');
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 style={{ padding: '0 8px' }}>
394
+ <div>
359
395
  <FormRender
360
396
  form={form}
361
397
  widgetList={widgetList}
398
+ onFieldsChange={onFieldsChange}
362
399
  />
363
- <div style={{ marginLeft: '120px' }}>
364
- <Button onClick={onSubmit}>submit</Button>
365
- </div>
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://img.shields.io/badge/version-3.0.8-green)](https://www.npmjs.com/package/@simpleform/render)
5
+ [![](https://img.shields.io/badge/version-3.0.10-green)](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
- export default function Demo(props) {
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
- const widgetList =
319
- [
320
- {
321
- label: "list-0",
322
- name: 'list[0]',
323
- rules: [{ required: true, message: 'list[0] empty' }],
324
- initialValue: 1,
325
- type: 'Input',
326
- props: {}
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
- label: "list-1",
330
- name: 'list[1]',
331
- rules: [{ required: true, message: 'list[1] empty' }],
332
- initialValue: 2,
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
- label: "list-2",
338
- name: 'list[2]',
339
- rules: [{ required: true, message: 'list[2] empty' }],
340
- initialValue: 3,
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
- label: "list-3",
346
- name: 'list[3]',
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 onSubmit = async (e) => {
355
- e?.preventDefault?.();
356
- const result = await form.validate();
357
- console.log(result, 'result');
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 style={{ padding: '0 8px' }}>
397
+ <div>
362
398
  <FormRender
363
399
  form={form}
364
400
  widgetList={widgetList}
401
+ onFieldsChange={onFieldsChange}
365
402
  />
366
- <div style={{ marginLeft: '120px' }}>
367
- <Button onClick={onSubmit}>submit</Button>
368
- </div>
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