@simpleform/render 3.0.7 → 3.0.9

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.7-green)](https://www.npmjs.com/package/@simpleform/render)
5
+ [![](https://img.shields.io/badge/version-3.0.9-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,103 @@ 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
+ className: classes.item
338
+ },
339
+ widgetList: [
325
340
  {
326
- label: "list-1",
327
- name: 'list[1]',
328
- rules: [{ required: true, message: 'list[1] empty' }],
329
- initialValue: 2,
341
+ name: `[${index}]label`,
342
+ compact: true,
343
+ outside: { type: 'col', props: { span: 9 } },
344
+ rules: [{ required: true }],
330
345
  type: 'Input',
331
- props: {}
346
+ props: {
347
+ placeholder: 'label',
348
+ style: { width: '100%' }
349
+ }
332
350
  },
333
351
  {
334
- label: "list-2",
335
- name: 'list[2]',
336
- rules: [{ required: true, message: 'list[2] empty' }],
337
- initialValue: 3,
352
+ name: `[${index}]value`,
353
+ compact: true,
354
+ outside: { type: 'col', props: { span: 9 } },
355
+ rules: [{ required: true }],
338
356
  type: 'Input',
339
- props: {}
357
+ props: {
358
+ placeholder: 'value',
359
+ style: { width: '100%' }
360
+ }
340
361
  },
341
362
  {
342
- label: "list-3",
343
- name: 'list[3]',
344
- rules: [{ required: true, message: 'list[3] empty' }],
345
- initialValue: 4,
346
- type: 'Input',
347
- props: {}
363
+ outside: { type: 'col', props: { span: 6 } },
364
+ typeRender: <Button type="link" onClick={() => deleteItem(index)}>delete</Button>
348
365
  },
349
- ];
366
+ ]
367
+ }));
368
+
369
+ const deleteItem = (index: number) => {
370
+ const oldData = [...dataSource];
371
+ if (!oldData) return;
372
+ const newData = [...oldData];
373
+ newData.splice(index, 1);
374
+ setDataSource(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 newDataSource = dataSource.concat(intialValue);
384
+ setDataSource(newDataSource);
385
+ };
386
+
387
+ const onFieldsChange: CustomFormRenderProps['onFieldsChange'] = ({ value }, values) => {
388
+ setDataSource(values);
389
+ onChange && onChange(values);
355
390
  };
356
391
 
357
392
  return (
358
- <div style={{ padding: '0 8px' }}>
393
+ <div>
359
394
  <FormRender
360
395
  form={form}
361
396
  widgetList={widgetList}
397
+ onFieldsChange={onFieldsChange}
362
398
  />
363
- <div style={{ marginLeft: '120px' }}>
364
- <Button onClick={onSubmit}>submit</Button>
365
- </div>
399
+ <Button type="link" onClick={addItem}>
400
+ add
401
+ </Button>
366
402
  </div>
367
403
  );
368
- }
404
+ });
405
+
406
+ export default OptionList;
369
407
  ```
370
408
  ## API
371
409
 
@@ -460,12 +498,13 @@ export interface GenerateParams<T = {}> {
460
498
  form?: SimpleForm;
461
499
  };
462
500
  ```
463
- ### Path path rules involved in forms
464
- Forms are allowed to be nested, so the form involves looking for a certain property. The paths follow certain rules
501
+ ### Rules for the name field of form controls
502
+ The `name` field can indicate the location path of a field in an array or object.
503
+
465
504
  Example:
466
- - `a[0]` denotes the first option below the array `a`
467
- - `a.b` denotes the `b` attribute of the `a` object
468
- - `a[0].b` represents the `b` attribute of the first option below the array `a`
505
+ - `a[0]` denotes the first option below the array a
506
+ - `a.b` indicates the b attribute of the a object
507
+ - `a[0].b` denotes the b attribute of the first option below array a
469
508
 
470
509
  ### String Expression Usage
471
510
  Property fields in a form node can support string expressions for linkage, except for `widgetList`.
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.7-green)](https://www.npmjs.com/package/@simpleform/render)
5
+ [![](https://img.shields.io/badge/version-3.0.9-green)](https://www.npmjs.com/package/@simpleform/render)
6
6
 
7
7
  > 轻量级动态表单引擎,实现动态渲染表单很简单.
8
8
 
@@ -308,67 +308,105 @@ 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
+ className: classes.item
341
+ },
342
+ widgetList: [
328
343
  {
329
- label: "list-1",
330
- name: 'list[1]',
331
- rules: [{ required: true, message: 'list[1] empty' }],
332
- initialValue: 2,
344
+ name: `[${index}]label`,
345
+ compact: true,
346
+ outside: { type: 'col', props: { span: 9 } },
347
+ rules: [{ required: true }],
333
348
  type: 'Input',
334
- props: {}
349
+ props: {
350
+ placeholder: 'label',
351
+ style: { width: '100%' }
352
+ }
335
353
  },
336
354
  {
337
- label: "list-2",
338
- name: 'list[2]',
339
- rules: [{ required: true, message: 'list[2] empty' }],
340
- initialValue: 3,
355
+ name: `[${index}]value`,
356
+ compact: true,
357
+ outside: { type: 'col', props: { span: 9 } },
358
+ rules: [{ required: true }],
341
359
  type: 'Input',
342
- props: {}
360
+ props: {
361
+ placeholder: 'value',
362
+ style: { width: '100%' }
363
+ }
343
364
  },
344
365
  {
345
- label: "list-3",
346
- name: 'list[3]',
347
- rules: [{ required: true, message: 'list[3] empty' }],
348
- initialValue: 4,
349
- type: 'Input',
350
- props: {}
366
+ outside: { type: 'col', props: { span: 6 } },
367
+ typeRender: <Button type="link" onClick={() => deleteItem(index)}>delete</Button>
351
368
  },
352
- ];
369
+ ]
370
+ }));
371
+
372
+ const deleteItem = (index: number) => {
373
+ const oldData = [...dataSource];
374
+ if (!oldData) return;
375
+ const newData = [...oldData];
376
+ newData.splice(index, 1);
377
+ setDataSource(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 newDataSource = dataSource.concat(intialValue);
387
+ setDataSource(newDataSource);
388
+ };
389
+
390
+ const onFieldsChange: CustomFormRenderProps['onFieldsChange'] = ({ value }, values) => {
391
+ setDataSource(values);
392
+ onChange && onChange(values);
358
393
  };
359
394
 
360
395
  return (
361
- <div style={{ padding: '0 8px' }}>
396
+ <div>
362
397
  <FormRender
363
398
  form={form}
364
399
  widgetList={widgetList}
400
+ onFieldsChange={onFieldsChange}
365
401
  />
366
- <div style={{ marginLeft: '120px' }}>
367
- <Button onClick={onSubmit}>submit</Button>
368
- </div>
402
+ <Button type="link" onClick={addItem}>
403
+ add
404
+ </Button>
369
405
  </div>
370
406
  );
371
- }
407
+ });
408
+
409
+ export default OptionList;
372
410
  ```
373
411
 
374
412
  ## API
@@ -465,8 +503,8 @@ export interface GenerateParams<T = {}> {
465
503
  form?: SimpleForm;
466
504
  };
467
505
  ```
468
- ### 表单的中涉及的path路径规则
469
- 表单允许嵌套,所以表单中会涉及寻找某个属性。其路径遵循一定的规则
506
+ ### 表单控件name字段的规则
507
+ `name`字段可表示数组或对象中某个属性字段的位置路径
470
508
 
471
509
  举例:
472
510
  - `a[0]`表示数组a下面的第一个选项