@simpleform/render 1.0.8 → 1.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 +549 -550
- package/README_CN.md +0 -1
- package/lib/index.js +1 -1
- package/package.json +9 -7
package/README.md
CHANGED
|
@@ -1,551 +1,550 @@
|
|
|
1
|
-
# `@simpleform/render`
|
|
2
|
-
|
|
3
|
-
English | [中文说明](./README_CN.md)
|
|
4
|
-
|
|
5
|
-
[](https://www.npmjs.com/package/@simpleform/render)
|
|
6
|
-
|
|
7
|
-
> A lightweight dynamic forms engine that makes it easy to dynamically render forms.
|
|
8
|
-
|
|
9
|
-
## Introduction
|
|
10
|
-
- Component Registration: Form controls used in `@simpleform/render` must be controlled components with `value` and `onChange` props.
|
|
11
|
-
- Component Description: `properties` supports rendering of object or array types, and adding nested object fields via the `properties` property.
|
|
12
|
-
- Component Rendering: `Form` component handles form values, `FormChildren` component handles form rendering, a `Form` component can support multiple `FormChildren` components rendering inside.
|
|
13
|
-
- Component linkage: All form properties can support string expressions to describe linkage conditions (except `properties`).
|
|
14
|
-
|
|
15
|
-
## install
|
|
16
|
-
- [Node.js](https://nodejs.org/en/) Version >= 14.0.0
|
|
17
|
-
- [react](https://react.docschina.org/) Version >= 16.8.0
|
|
18
|
-
```bash
|
|
19
|
-
npm install @simpleform/render --save
|
|
20
|
-
# 或者
|
|
21
|
-
yarn add @simpleform/render
|
|
22
|
-
```
|
|
23
|
-
## Quick Start
|
|
24
|
-
|
|
25
|
-
### 1. First register the basic components (Take antd@5.x as an example)
|
|
26
|
-
```javascript
|
|
27
|
-
// register
|
|
28
|
-
import FormRenderCore, { FormChildren as FormChildrenCore, FormNodeProps, FormRenderProps, FormChildrenProps, GenerateParams } from '@simpleform/render';
|
|
29
|
-
import '@simpleform/render/lib/css/main.css';
|
|
30
|
-
import React from 'react';
|
|
31
|
-
import dayjs from 'dayjs';
|
|
32
|
-
import {
|
|
33
|
-
Input,
|
|
34
|
-
InputNumber,
|
|
35
|
-
Checkbox,
|
|
36
|
-
DatePicker,
|
|
37
|
-
Mentions,
|
|
38
|
-
Radio,
|
|
39
|
-
Rate,
|
|
40
|
-
Select,
|
|
41
|
-
Slider,
|
|
42
|
-
Switch,
|
|
43
|
-
TimePicker,
|
|
44
|
-
} from 'antd';
|
|
45
|
-
|
|
46
|
-
export * from '@simpleform/render';
|
|
47
|
-
|
|
48
|
-
export const widgets = {
|
|
49
|
-
"Input": Input,
|
|
50
|
-
"Input.TextArea": Input.TextArea,
|
|
51
|
-
"Input.Password": Input.Password,
|
|
52
|
-
"Input.Search": Input.Search,
|
|
53
|
-
"InputNumber": InputNumber,
|
|
54
|
-
"Checkbox": Checkbox,
|
|
55
|
-
'Checkbox.Group': Checkbox.Group,
|
|
56
|
-
"DatePicker": DatePicker,
|
|
57
|
-
"DatePicker.RangePicker": DatePicker.RangePicker,
|
|
58
|
-
"Mentions": Mentions,
|
|
59
|
-
"Mentions.Option": Mentions.Option,
|
|
60
|
-
"Radio": Radio,
|
|
61
|
-
"Radio.Group": Radio.Group,
|
|
62
|
-
"Radio.Button": Radio.Button,
|
|
63
|
-
"Rate": Rate,
|
|
64
|
-
"Select": Select,
|
|
65
|
-
"Select.Option": Select.Option,
|
|
66
|
-
"TreeSelect": TreeSelect,
|
|
67
|
-
"Slider": Slider,
|
|
68
|
-
"Switch": Switch,
|
|
69
|
-
"TimePicker": TimePicker,
|
|
70
|
-
"TimePicker.RangePicker": TimePicker.RangePicker
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
export type CustomFormChildrenProps = FormChildrenProps<any>;
|
|
74
|
-
export function FormChildren(props: CustomFormChildrenProps) {
|
|
75
|
-
const { components, plugins, ...rest } = props;
|
|
76
|
-
return (
|
|
77
|
-
<FormChildrenCore
|
|
78
|
-
options={{ props: { autoComplete: 'off' } }}
|
|
79
|
-
components={{ ...widgets, ...components }}
|
|
80
|
-
plugins={{ ...plugins, dayjs }}
|
|
81
|
-
{...rest}
|
|
82
|
-
/>
|
|
83
|
-
);
|
|
84
|
-
}
|
|
85
|
-
export type CustomFormRenderProps = FormRenderProps<any>;
|
|
86
|
-
export default function FormRender(props: CustomFormRenderProps) {
|
|
87
|
-
const { components, plugins, ...rest } = props;
|
|
88
|
-
return (
|
|
89
|
-
<FormRenderCore
|
|
90
|
-
options={{ props: { autoComplete: 'off' } }}
|
|
91
|
-
components={{ ...widgets, ...components }}
|
|
92
|
-
plugins={{ ...plugins, dayjs }}
|
|
93
|
-
{...rest}
|
|
94
|
-
/>
|
|
95
|
-
);
|
|
96
|
-
}
|
|
97
|
-
```
|
|
98
|
-
### 2. Introduce the components that were registered in the first step.
|
|
99
|
-
```javascript
|
|
100
|
-
import { Button } from 'antd';
|
|
101
|
-
import React, { useState } from 'react';
|
|
102
|
-
import FormRender, { useSimpleForm, useSimpleFormRender } from './form-render';
|
|
103
|
-
export default function Demo5(props) {
|
|
104
|
-
|
|
105
|
-
const watch = {
|
|
106
|
-
'name2': (newValue, oldValue) => {
|
|
107
|
-
console.log(newValue, oldValue)
|
|
108
|
-
},
|
|
109
|
-
'name3[0]': (newValue, oldValue) => {
|
|
110
|
-
console.log(newValue, oldValue)
|
|
111
|
-
},
|
|
112
|
-
'name4': (newValue, oldValue) => {
|
|
113
|
-
console.log(newValue, oldValue)
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
const properties = {
|
|
118
|
-
name1: {
|
|
119
|
-
label: "readonly",
|
|
120
|
-
readOnly: true,
|
|
121
|
-
readOnlyRender: "readonly component",
|
|
122
|
-
initialValue: 1111,
|
|
123
|
-
hidden: '{{formvalues && formvalues.name6 == true}}',
|
|
124
|
-
type: 'Input',
|
|
125
|
-
props: {}
|
|
126
|
-
},
|
|
127
|
-
name2: {
|
|
128
|
-
label: "input",
|
|
129
|
-
rules: [{ required: true, message: 'input empty' }],
|
|
130
|
-
initialValue: 1,
|
|
131
|
-
hidden: '{{formvalues && formvalues.name6 == true}}',
|
|
132
|
-
type: 'Input',
|
|
133
|
-
props: {}
|
|
134
|
-
},
|
|
135
|
-
name3: {
|
|
136
|
-
// type: '',
|
|
137
|
-
// props: {},
|
|
138
|
-
properties: [{
|
|
139
|
-
label: 'list[0]',
|
|
140
|
-
rules: [{ required: true, message: 'list[0] empty' }],
|
|
141
|
-
initialValue: { label: 'option1', value: '1', key: '1' },
|
|
142
|
-
type: 'Select',
|
|
143
|
-
props: {
|
|
144
|
-
labelInValue: true,
|
|
145
|
-
style: { width: '100%' },
|
|
146
|
-
children: [
|
|
147
|
-
{ type: 'Select.Option', props: { key: 1, value: '1', children: 'option1' } },
|
|
148
|
-
{ type: 'Select.Option', props: { key: 2, value: '2', children: 'option2' } }
|
|
149
|
-
]
|
|
150
|
-
}
|
|
151
|
-
}, {
|
|
152
|
-
label: 'list[1]',
|
|
153
|
-
rules: [{ required: true, message: 'list[1] empty' }],
|
|
154
|
-
type: 'Select',
|
|
155
|
-
props: {
|
|
156
|
-
labelInValue: true,
|
|
157
|
-
style: { width: '100%' },
|
|
158
|
-
children: [
|
|
159
|
-
{ type: 'Select.Option', props: { key: 1, value: '1', children: 'option1' } },
|
|
160
|
-
{ type: 'Select.Option', props: { key: 2, value: '2', children: 'option2' } }
|
|
161
|
-
]
|
|
162
|
-
}
|
|
163
|
-
}]
|
|
164
|
-
},
|
|
165
|
-
name4: {
|
|
166
|
-
// type: '',
|
|
167
|
-
// props: {},
|
|
168
|
-
properties: {
|
|
169
|
-
first: {
|
|
170
|
-
label: 'first',
|
|
171
|
-
rules: [{ required: true, message: 'first empty' }],
|
|
172
|
-
type: 'Select',
|
|
173
|
-
props: {
|
|
174
|
-
style: { width: '100%' },
|
|
175
|
-
children: [{ type: 'Select.Option', props: { key: 1, value: '1', children: 'option1' } }]
|
|
176
|
-
}
|
|
177
|
-
},
|
|
178
|
-
second: {
|
|
179
|
-
label: 'second',
|
|
180
|
-
rules: [{ required: true, message: 'second empty' }],
|
|
181
|
-
type: 'Select',
|
|
182
|
-
props: {
|
|
183
|
-
style: { width: '100%' },
|
|
184
|
-
children: [{ type: 'Select.Option', props: { key: 1, value: '1', children: 'option1' } }]
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
},
|
|
189
|
-
name5: {
|
|
190
|
-
label: 'name5',
|
|
191
|
-
initialValue: { span: 12 },
|
|
192
|
-
valueSetter: "{{(value)=> (value && value['span'])}}",
|
|
193
|
-
valueGetter: "{{(value) => ({span: value})}}",
|
|
194
|
-
type: 'Select',
|
|
195
|
-
props: {
|
|
196
|
-
style: { width: '100%' },
|
|
197
|
-
children: [
|
|
198
|
-
{ type: 'Select.Option', props: { key: 1, value: 12, children: 'option1' } },
|
|
199
|
-
{ type: 'Select.Option', props: { key: 2, value: 6, children: 'option2' } },
|
|
200
|
-
{ type: 'Select.Option', props: { key: 3, value: 4, children: 'option3' } }
|
|
201
|
-
]
|
|
202
|
-
}
|
|
203
|
-
},
|
|
204
|
-
name6: {
|
|
205
|
-
label: 'checkbox',
|
|
206
|
-
valueProp: 'checked',
|
|
207
|
-
initialValue: true,
|
|
208
|
-
rules: [{ required: true, message: 'checkbox empty' }],
|
|
209
|
-
type: 'Checkbox',
|
|
210
|
-
props: {
|
|
211
|
-
style: { width: '100%' },
|
|
212
|
-
children: 'option'
|
|
213
|
-
}
|
|
214
|
-
},
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
const form = useSimpleForm();
|
|
218
|
-
// const formrender = useSimpleFormRender();
|
|
219
|
-
|
|
220
|
-
const onSubmit = async (e) => {
|
|
221
|
-
e?.preventDefault?.();
|
|
222
|
-
const result = await form.validate();
|
|
223
|
-
console.log(result, 'result');
|
|
224
|
-
};
|
|
225
|
-
|
|
226
|
-
return (
|
|
227
|
-
<div>
|
|
228
|
-
<FormRender
|
|
229
|
-
form={form}
|
|
230
|
-
// formrender={formrender}
|
|
231
|
-
properties={properties}
|
|
232
|
-
watch={watch} />
|
|
233
|
-
<div style={{ marginLeft: '120px' }}>
|
|
234
|
-
<Button onClick={onSubmit}>submit</Button>
|
|
235
|
-
</div>
|
|
236
|
-
</div>
|
|
237
|
-
);
|
|
238
|
-
}
|
|
239
|
-
```
|
|
240
|
-
### 3. Multi-module rendering
|
|
241
|
-
The form engine also supports rendering by multiple `FormChildren` components, which then unify the processing of form values by the `Form` component.
|
|
242
|
-
- `useSimpleForm`: Creates a managed instance of a form value.
|
|
243
|
-
- `useSimpleFormRender`: creates an instance that renders the form.
|
|
244
|
-
```javascript
|
|
245
|
-
import React, { useState } from 'react';
|
|
246
|
-
import { FormChildren, Form, useSimpleForm } from './form-render';
|
|
247
|
-
import { Button } from 'antd';
|
|
248
|
-
export default function Demo(props) {
|
|
249
|
-
|
|
250
|
-
const properties1 = {
|
|
251
|
-
part1: {
|
|
252
|
-
label: "part1input",
|
|
253
|
-
rules: [{ required: true, message: 'name1 empty' }],
|
|
254
|
-
initialValue: 1,
|
|
255
|
-
type: 'Input',
|
|
256
|
-
props: {}
|
|
257
|
-
},
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
const properties2 = {
|
|
261
|
-
part2: {
|
|
262
|
-
label: "part2input",
|
|
263
|
-
rules: [{ required: true, message: 'name1 empty' }],
|
|
264
|
-
initialValue: 1,
|
|
265
|
-
type: 'Input',
|
|
266
|
-
props: {}
|
|
267
|
-
},
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
const form = useSimpleForm();
|
|
271
|
-
// const formrender1 = useSimpleFormRender()
|
|
272
|
-
// const formrender2 = useSimpleFormRender()
|
|
273
|
-
|
|
274
|
-
const onSubmit = async (e) => {
|
|
275
|
-
e?.preventDefault?.();
|
|
276
|
-
const result = await form.validate();
|
|
277
|
-
console.log(result, 'result');
|
|
278
|
-
};
|
|
279
|
-
|
|
280
|
-
return (
|
|
281
|
-
<div style={{ padding: '0 8px' }}>
|
|
282
|
-
<Form form={form}>
|
|
283
|
-
<div>
|
|
284
|
-
<p>part1</p>
|
|
285
|
-
<FormChildren
|
|
286
|
-
// formrender={formrender1}
|
|
287
|
-
properties={properties1}
|
|
288
|
-
/>
|
|
289
|
-
</div>
|
|
290
|
-
<div>
|
|
291
|
-
<p>part2</p>
|
|
292
|
-
<FormChildren
|
|
293
|
-
// formrender={formrender2}
|
|
294
|
-
properties={properties2}
|
|
295
|
-
/>
|
|
296
|
-
</div>
|
|
297
|
-
</Form>
|
|
298
|
-
<div style={{ marginLeft: '120px' }}>
|
|
299
|
-
<Button onClick={onSubmit}>submit</Button>
|
|
300
|
-
</div>
|
|
301
|
-
</div>
|
|
302
|
-
);
|
|
303
|
-
}
|
|
304
|
-
```
|
|
305
|
-
### 4. List Demo
|
|
306
|
-
支持数组渲染
|
|
307
|
-
```javascript
|
|
308
|
-
import React, { useState } from 'react';
|
|
309
|
-
import FormRender, { useSimpleForm } from './form-render';
|
|
310
|
-
import { Button } from 'antd';
|
|
311
|
-
export default function Demo(props) {
|
|
312
|
-
const form = useSimpleForm();
|
|
313
|
-
const properties =
|
|
314
|
-
[
|
|
315
|
-
{
|
|
316
|
-
label: "list-0",
|
|
317
|
-
rules: [{ required: true, message: 'name1 empty' }],
|
|
318
|
-
initialValue: 1,
|
|
319
|
-
type: 'Input',
|
|
320
|
-
props: {}
|
|
321
|
-
},
|
|
322
|
-
{
|
|
323
|
-
label: "list-1",
|
|
324
|
-
rules: [{ required: true, message: 'name1 empty' }],
|
|
325
|
-
initialValue: 2,
|
|
326
|
-
type: 'Input',
|
|
327
|
-
props: {}
|
|
328
|
-
},
|
|
329
|
-
{
|
|
330
|
-
label: "list-2",
|
|
331
|
-
rules: [{ required: true, message: 'name1 empty' }],
|
|
332
|
-
initialValue: 3,
|
|
333
|
-
type: 'Input',
|
|
334
|
-
props: {}
|
|
335
|
-
},
|
|
336
|
-
{
|
|
337
|
-
label: "list-3",
|
|
338
|
-
rules: [{ required: true, message: 'name1 empty' }],
|
|
339
|
-
initialValue: 4,
|
|
340
|
-
type: 'Input',
|
|
341
|
-
props: {}
|
|
342
|
-
},
|
|
343
|
-
];
|
|
344
|
-
|
|
345
|
-
const onSubmit = async (e) => {
|
|
346
|
-
e?.preventDefault?.();
|
|
347
|
-
const result = await form.validate();
|
|
348
|
-
console.log(result, 'result');
|
|
349
|
-
};
|
|
350
|
-
|
|
351
|
-
return (
|
|
352
|
-
<div style={{ padding: '0 8px' }}>
|
|
353
|
-
<FormRender
|
|
354
|
-
form={form}
|
|
355
|
-
properties={properties}
|
|
356
|
-
/>
|
|
357
|
-
<div style={{ marginLeft: '120px' }}>
|
|
358
|
-
<Button onClick={onSubmit}>submit</Button>
|
|
359
|
-
</div>
|
|
360
|
-
</div>
|
|
361
|
-
);
|
|
362
|
-
}
|
|
363
|
-
```
|
|
364
|
-
## API
|
|
365
|
-
|
|
366
|
-
### Form`s props
|
|
367
|
-
Sourced from [@simpleform/form](
|
|
368
|
-
|
|
369
|
-
### FormChildren's props
|
|
370
|
-
- `properties`: `{ [name: string]: FormNodeProps } | FormNodeProps[]` Renders the form's DSL form json data
|
|
371
|
-
- `components`: registers all components in the form.
|
|
372
|
-
- `plugins`: foreign libraries to be introduced in the form.
|
|
373
|
-
- `options`: `GenerateFormNodeProps | ((field: GenerateFormNodeProps) => any)` Parameter information passed to the form node components. The priority is lower than the form node's own parameters
|
|
374
|
-
- `renderList`: Provides a function to customize the rendered list.
|
|
375
|
-
- `renderItem`: provides a function to customize the rendering of the node.
|
|
376
|
-
- `onPropertiesChange`: `(newValue: PropertiesData) => void;` `Properties` change callback function.
|
|
377
|
-
- `formrender`: The form class responsible for rendering. Created by `useSimpleFormRender()`, optional.
|
|
378
|
-
- `form`: Class responsible for the value of the form. Created via `useSimpleForm()`, optional.
|
|
379
|
-
- `uneval`: does not execute string expressions in the form.
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
- `
|
|
384
|
-
- `
|
|
385
|
-
- `
|
|
386
|
-
- `
|
|
387
|
-
- `
|
|
388
|
-
- `
|
|
389
|
-
- `
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
- `
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
//
|
|
408
|
-
//
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
| React.
|
|
434
|
-
| React.
|
|
435
|
-
| React.
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
[key in keyof
|
|
456
|
-
(
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
field?: GenerateFormNodeProps<T>;
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
- `a
|
|
487
|
-
- `a.b`
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
import
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
<FormRender properties={properties} plugins={{ dayjs }} />
|
|
1
|
+
# `@simpleform/render`
|
|
2
|
+
|
|
3
|
+
English | [中文说明](./README_CN.md)
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/@simpleform/render)
|
|
6
|
+
|
|
7
|
+
> A lightweight dynamic forms engine that makes it easy to dynamically render forms.
|
|
8
|
+
|
|
9
|
+
## Introduction
|
|
10
|
+
- Component Registration: Form controls used in `@simpleform/render` must be controlled components with `value` and `onChange` props.
|
|
11
|
+
- Component Description: `properties` supports rendering of object or array types, and adding nested object fields via the `properties` property.
|
|
12
|
+
- Component Rendering: `Form` component handles form values, `FormChildren` component handles form rendering, a `Form` component can support multiple `FormChildren` components rendering inside.
|
|
13
|
+
- Component linkage: All form properties can support string expressions to describe linkage conditions (except `properties`).
|
|
14
|
+
|
|
15
|
+
## install
|
|
16
|
+
- [Node.js](https://nodejs.org/en/) Version >= 14.0.0
|
|
17
|
+
- [react](https://react.docschina.org/) Version >= 16.8.0
|
|
18
|
+
```bash
|
|
19
|
+
npm install @simpleform/render --save
|
|
20
|
+
# 或者
|
|
21
|
+
yarn add @simpleform/render
|
|
22
|
+
```
|
|
23
|
+
## Quick Start
|
|
24
|
+
|
|
25
|
+
### 1. First register the basic components (Take antd@5.x as an example)
|
|
26
|
+
```javascript
|
|
27
|
+
// register
|
|
28
|
+
import FormRenderCore, { FormChildren as FormChildrenCore, FormNodeProps, FormRenderProps, FormChildrenProps, GenerateParams } from '@simpleform/render';
|
|
29
|
+
import '@simpleform/render/lib/css/main.css';
|
|
30
|
+
import React from 'react';
|
|
31
|
+
import dayjs from 'dayjs';
|
|
32
|
+
import {
|
|
33
|
+
Input,
|
|
34
|
+
InputNumber,
|
|
35
|
+
Checkbox,
|
|
36
|
+
DatePicker,
|
|
37
|
+
Mentions,
|
|
38
|
+
Radio,
|
|
39
|
+
Rate,
|
|
40
|
+
Select,
|
|
41
|
+
Slider,
|
|
42
|
+
Switch,
|
|
43
|
+
TimePicker,
|
|
44
|
+
} from 'antd';
|
|
45
|
+
|
|
46
|
+
export * from '@simpleform/render';
|
|
47
|
+
|
|
48
|
+
export const widgets = {
|
|
49
|
+
"Input": Input,
|
|
50
|
+
"Input.TextArea": Input.TextArea,
|
|
51
|
+
"Input.Password": Input.Password,
|
|
52
|
+
"Input.Search": Input.Search,
|
|
53
|
+
"InputNumber": InputNumber,
|
|
54
|
+
"Checkbox": Checkbox,
|
|
55
|
+
'Checkbox.Group': Checkbox.Group,
|
|
56
|
+
"DatePicker": DatePicker,
|
|
57
|
+
"DatePicker.RangePicker": DatePicker.RangePicker,
|
|
58
|
+
"Mentions": Mentions,
|
|
59
|
+
"Mentions.Option": Mentions.Option,
|
|
60
|
+
"Radio": Radio,
|
|
61
|
+
"Radio.Group": Radio.Group,
|
|
62
|
+
"Radio.Button": Radio.Button,
|
|
63
|
+
"Rate": Rate,
|
|
64
|
+
"Select": Select,
|
|
65
|
+
"Select.Option": Select.Option,
|
|
66
|
+
"TreeSelect": TreeSelect,
|
|
67
|
+
"Slider": Slider,
|
|
68
|
+
"Switch": Switch,
|
|
69
|
+
"TimePicker": TimePicker,
|
|
70
|
+
"TimePicker.RangePicker": TimePicker.RangePicker
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export type CustomFormChildrenProps = FormChildrenProps<any>;
|
|
74
|
+
export function FormChildren(props: CustomFormChildrenProps) {
|
|
75
|
+
const { components, plugins, ...rest } = props;
|
|
76
|
+
return (
|
|
77
|
+
<FormChildrenCore
|
|
78
|
+
options={{ props: { autoComplete: 'off' } }}
|
|
79
|
+
components={{ ...widgets, ...components }}
|
|
80
|
+
plugins={{ ...plugins, dayjs }}
|
|
81
|
+
{...rest}
|
|
82
|
+
/>
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
export type CustomFormRenderProps = FormRenderProps<any>;
|
|
86
|
+
export default function FormRender(props: CustomFormRenderProps) {
|
|
87
|
+
const { components, plugins, ...rest } = props;
|
|
88
|
+
return (
|
|
89
|
+
<FormRenderCore
|
|
90
|
+
options={{ props: { autoComplete: 'off' } }}
|
|
91
|
+
components={{ ...widgets, ...components }}
|
|
92
|
+
plugins={{ ...plugins, dayjs }}
|
|
93
|
+
{...rest}
|
|
94
|
+
/>
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
```
|
|
98
|
+
### 2. Introduce the components that were registered in the first step.
|
|
99
|
+
```javascript
|
|
100
|
+
import { Button } from 'antd';
|
|
101
|
+
import React, { useState } from 'react';
|
|
102
|
+
import FormRender, { useSimpleForm, useSimpleFormRender } from './form-render';
|
|
103
|
+
export default function Demo5(props) {
|
|
104
|
+
|
|
105
|
+
const watch = {
|
|
106
|
+
'name2': (newValue, oldValue) => {
|
|
107
|
+
console.log(newValue, oldValue)
|
|
108
|
+
},
|
|
109
|
+
'name3[0]': (newValue, oldValue) => {
|
|
110
|
+
console.log(newValue, oldValue)
|
|
111
|
+
},
|
|
112
|
+
'name4': (newValue, oldValue) => {
|
|
113
|
+
console.log(newValue, oldValue)
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
const properties = {
|
|
118
|
+
name1: {
|
|
119
|
+
label: "readonly",
|
|
120
|
+
readOnly: true,
|
|
121
|
+
readOnlyRender: "readonly component",
|
|
122
|
+
initialValue: 1111,
|
|
123
|
+
hidden: '{{formvalues && formvalues.name6 == true}}',
|
|
124
|
+
type: 'Input',
|
|
125
|
+
props: {}
|
|
126
|
+
},
|
|
127
|
+
name2: {
|
|
128
|
+
label: "input",
|
|
129
|
+
rules: [{ required: true, message: 'input empty' }],
|
|
130
|
+
initialValue: 1,
|
|
131
|
+
hidden: '{{formvalues && formvalues.name6 == true}}',
|
|
132
|
+
type: 'Input',
|
|
133
|
+
props: {}
|
|
134
|
+
},
|
|
135
|
+
name3: {
|
|
136
|
+
// type: '',
|
|
137
|
+
// props: {},
|
|
138
|
+
properties: [{
|
|
139
|
+
label: 'list[0]',
|
|
140
|
+
rules: [{ required: true, message: 'list[0] empty' }],
|
|
141
|
+
initialValue: { label: 'option1', value: '1', key: '1' },
|
|
142
|
+
type: 'Select',
|
|
143
|
+
props: {
|
|
144
|
+
labelInValue: true,
|
|
145
|
+
style: { width: '100%' },
|
|
146
|
+
children: [
|
|
147
|
+
{ type: 'Select.Option', props: { key: 1, value: '1', children: 'option1' } },
|
|
148
|
+
{ type: 'Select.Option', props: { key: 2, value: '2', children: 'option2' } }
|
|
149
|
+
]
|
|
150
|
+
}
|
|
151
|
+
}, {
|
|
152
|
+
label: 'list[1]',
|
|
153
|
+
rules: [{ required: true, message: 'list[1] empty' }],
|
|
154
|
+
type: 'Select',
|
|
155
|
+
props: {
|
|
156
|
+
labelInValue: true,
|
|
157
|
+
style: { width: '100%' },
|
|
158
|
+
children: [
|
|
159
|
+
{ type: 'Select.Option', props: { key: 1, value: '1', children: 'option1' } },
|
|
160
|
+
{ type: 'Select.Option', props: { key: 2, value: '2', children: 'option2' } }
|
|
161
|
+
]
|
|
162
|
+
}
|
|
163
|
+
}]
|
|
164
|
+
},
|
|
165
|
+
name4: {
|
|
166
|
+
// type: '',
|
|
167
|
+
// props: {},
|
|
168
|
+
properties: {
|
|
169
|
+
first: {
|
|
170
|
+
label: 'first',
|
|
171
|
+
rules: [{ required: true, message: 'first empty' }],
|
|
172
|
+
type: 'Select',
|
|
173
|
+
props: {
|
|
174
|
+
style: { width: '100%' },
|
|
175
|
+
children: [{ type: 'Select.Option', props: { key: 1, value: '1', children: 'option1' } }]
|
|
176
|
+
}
|
|
177
|
+
},
|
|
178
|
+
second: {
|
|
179
|
+
label: 'second',
|
|
180
|
+
rules: [{ required: true, message: 'second empty' }],
|
|
181
|
+
type: 'Select',
|
|
182
|
+
props: {
|
|
183
|
+
style: { width: '100%' },
|
|
184
|
+
children: [{ type: 'Select.Option', props: { key: 1, value: '1', children: 'option1' } }]
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
},
|
|
189
|
+
name5: {
|
|
190
|
+
label: 'name5',
|
|
191
|
+
initialValue: { span: 12 },
|
|
192
|
+
valueSetter: "{{(value)=> (value && value['span'])}}",
|
|
193
|
+
valueGetter: "{{(value) => ({span: value})}}",
|
|
194
|
+
type: 'Select',
|
|
195
|
+
props: {
|
|
196
|
+
style: { width: '100%' },
|
|
197
|
+
children: [
|
|
198
|
+
{ type: 'Select.Option', props: { key: 1, value: 12, children: 'option1' } },
|
|
199
|
+
{ type: 'Select.Option', props: { key: 2, value: 6, children: 'option2' } },
|
|
200
|
+
{ type: 'Select.Option', props: { key: 3, value: 4, children: 'option3' } }
|
|
201
|
+
]
|
|
202
|
+
}
|
|
203
|
+
},
|
|
204
|
+
name6: {
|
|
205
|
+
label: 'checkbox',
|
|
206
|
+
valueProp: 'checked',
|
|
207
|
+
initialValue: true,
|
|
208
|
+
rules: [{ required: true, message: 'checkbox empty' }],
|
|
209
|
+
type: 'Checkbox',
|
|
210
|
+
props: {
|
|
211
|
+
style: { width: '100%' },
|
|
212
|
+
children: 'option'
|
|
213
|
+
}
|
|
214
|
+
},
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
const form = useSimpleForm();
|
|
218
|
+
// const formrender = useSimpleFormRender();
|
|
219
|
+
|
|
220
|
+
const onSubmit = async (e) => {
|
|
221
|
+
e?.preventDefault?.();
|
|
222
|
+
const result = await form.validate();
|
|
223
|
+
console.log(result, 'result');
|
|
224
|
+
};
|
|
225
|
+
|
|
226
|
+
return (
|
|
227
|
+
<div>
|
|
228
|
+
<FormRender
|
|
229
|
+
form={form}
|
|
230
|
+
// formrender={formrender}
|
|
231
|
+
properties={properties}
|
|
232
|
+
watch={watch} />
|
|
233
|
+
<div style={{ marginLeft: '120px' }}>
|
|
234
|
+
<Button onClick={onSubmit}>submit</Button>
|
|
235
|
+
</div>
|
|
236
|
+
</div>
|
|
237
|
+
);
|
|
238
|
+
}
|
|
239
|
+
```
|
|
240
|
+
### 3. Multi-module rendering
|
|
241
|
+
The form engine also supports rendering by multiple `FormChildren` components, which then unify the processing of form values by the `Form` component.
|
|
242
|
+
- `useSimpleForm`: Creates a managed instance of a form value.
|
|
243
|
+
- `useSimpleFormRender`: creates an instance that renders the form.
|
|
244
|
+
```javascript
|
|
245
|
+
import React, { useState } from 'react';
|
|
246
|
+
import { FormChildren, Form, useSimpleForm } from './form-render';
|
|
247
|
+
import { Button } from 'antd';
|
|
248
|
+
export default function Demo(props) {
|
|
249
|
+
|
|
250
|
+
const properties1 = {
|
|
251
|
+
part1: {
|
|
252
|
+
label: "part1input",
|
|
253
|
+
rules: [{ required: true, message: 'name1 empty' }],
|
|
254
|
+
initialValue: 1,
|
|
255
|
+
type: 'Input',
|
|
256
|
+
props: {}
|
|
257
|
+
},
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
const properties2 = {
|
|
261
|
+
part2: {
|
|
262
|
+
label: "part2input",
|
|
263
|
+
rules: [{ required: true, message: 'name1 empty' }],
|
|
264
|
+
initialValue: 1,
|
|
265
|
+
type: 'Input',
|
|
266
|
+
props: {}
|
|
267
|
+
},
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
const form = useSimpleForm();
|
|
271
|
+
// const formrender1 = useSimpleFormRender()
|
|
272
|
+
// const formrender2 = useSimpleFormRender()
|
|
273
|
+
|
|
274
|
+
const onSubmit = async (e) => {
|
|
275
|
+
e?.preventDefault?.();
|
|
276
|
+
const result = await form.validate();
|
|
277
|
+
console.log(result, 'result');
|
|
278
|
+
};
|
|
279
|
+
|
|
280
|
+
return (
|
|
281
|
+
<div style={{ padding: '0 8px' }}>
|
|
282
|
+
<Form form={form}>
|
|
283
|
+
<div>
|
|
284
|
+
<p>part1</p>
|
|
285
|
+
<FormChildren
|
|
286
|
+
// formrender={formrender1}
|
|
287
|
+
properties={properties1}
|
|
288
|
+
/>
|
|
289
|
+
</div>
|
|
290
|
+
<div>
|
|
291
|
+
<p>part2</p>
|
|
292
|
+
<FormChildren
|
|
293
|
+
// formrender={formrender2}
|
|
294
|
+
properties={properties2}
|
|
295
|
+
/>
|
|
296
|
+
</div>
|
|
297
|
+
</Form>
|
|
298
|
+
<div style={{ marginLeft: '120px' }}>
|
|
299
|
+
<Button onClick={onSubmit}>submit</Button>
|
|
300
|
+
</div>
|
|
301
|
+
</div>
|
|
302
|
+
);
|
|
303
|
+
}
|
|
304
|
+
```
|
|
305
|
+
### 4. List Demo
|
|
306
|
+
支持数组渲染
|
|
307
|
+
```javascript
|
|
308
|
+
import React, { useState } from 'react';
|
|
309
|
+
import FormRender, { useSimpleForm } from './form-render';
|
|
310
|
+
import { Button } from 'antd';
|
|
311
|
+
export default function Demo(props) {
|
|
312
|
+
const form = useSimpleForm();
|
|
313
|
+
const properties =
|
|
314
|
+
[
|
|
315
|
+
{
|
|
316
|
+
label: "list-0",
|
|
317
|
+
rules: [{ required: true, message: 'name1 empty' }],
|
|
318
|
+
initialValue: 1,
|
|
319
|
+
type: 'Input',
|
|
320
|
+
props: {}
|
|
321
|
+
},
|
|
322
|
+
{
|
|
323
|
+
label: "list-1",
|
|
324
|
+
rules: [{ required: true, message: 'name1 empty' }],
|
|
325
|
+
initialValue: 2,
|
|
326
|
+
type: 'Input',
|
|
327
|
+
props: {}
|
|
328
|
+
},
|
|
329
|
+
{
|
|
330
|
+
label: "list-2",
|
|
331
|
+
rules: [{ required: true, message: 'name1 empty' }],
|
|
332
|
+
initialValue: 3,
|
|
333
|
+
type: 'Input',
|
|
334
|
+
props: {}
|
|
335
|
+
},
|
|
336
|
+
{
|
|
337
|
+
label: "list-3",
|
|
338
|
+
rules: [{ required: true, message: 'name1 empty' }],
|
|
339
|
+
initialValue: 4,
|
|
340
|
+
type: 'Input',
|
|
341
|
+
props: {}
|
|
342
|
+
},
|
|
343
|
+
];
|
|
344
|
+
|
|
345
|
+
const onSubmit = async (e) => {
|
|
346
|
+
e?.preventDefault?.();
|
|
347
|
+
const result = await form.validate();
|
|
348
|
+
console.log(result, 'result');
|
|
349
|
+
};
|
|
350
|
+
|
|
351
|
+
return (
|
|
352
|
+
<div style={{ padding: '0 8px' }}>
|
|
353
|
+
<FormRender
|
|
354
|
+
form={form}
|
|
355
|
+
properties={properties}
|
|
356
|
+
/>
|
|
357
|
+
<div style={{ marginLeft: '120px' }}>
|
|
358
|
+
<Button onClick={onSubmit}>submit</Button>
|
|
359
|
+
</div>
|
|
360
|
+
</div>
|
|
361
|
+
);
|
|
362
|
+
}
|
|
363
|
+
```
|
|
364
|
+
## API
|
|
365
|
+
|
|
366
|
+
### Form`s props
|
|
367
|
+
Sourced from [@simpleform/form](../form);
|
|
368
|
+
|
|
369
|
+
### FormChildren's props
|
|
370
|
+
- `properties`: `{ [name: string]: FormNodeProps } | FormNodeProps[]` Renders the form's DSL form json data
|
|
371
|
+
- `components`: registers all components in the form.
|
|
372
|
+
- `plugins`: foreign libraries to be introduced in the form.
|
|
373
|
+
- `options`: `GenerateFormNodeProps | ((field: GenerateFormNodeProps) => any)` Parameter information passed to the form node components. The priority is lower than the form node's own parameters
|
|
374
|
+
- `renderList`: Provides a function to customize the rendered list.
|
|
375
|
+
- `renderItem`: provides a function to customize the rendering of the node.
|
|
376
|
+
- `onPropertiesChange`: `(newValue: PropertiesData) => void;` `Properties` change callback function.
|
|
377
|
+
- `formrender`: The form class responsible for rendering. Created by `useSimpleFormRender()`, optional.
|
|
378
|
+
- `form`: Class responsible for the value of the form. Created via `useSimpleForm()`, optional.
|
|
379
|
+
- `uneval`: does not execute string expressions in the form.
|
|
380
|
+
|
|
381
|
+
### SimpleFormRender's Methods
|
|
382
|
+
- `updateItemByPath`: `(data?: any, path?: string, attributeName?: string) => void` Updates the node corresponding to the path `path`, if updating a specific attribute in the node then the `attributeName` parameter is required.
|
|
383
|
+
- `setItemByPath`: `(data?: any, path?: string, attributeName?: string) => void` Sets the node corresponding to the path `path`, the `attributeName` parameter is required if you are updating a specific attribute in the node.
|
|
384
|
+
- `updateNameByPath`: `(newName?: string, path: string) => void` Updates the name key of the specified path.
|
|
385
|
+
- `delItemByPath`: `(path?: string, attributeName?: string) => void` Deletes the node corresponding to the path `path`, if deleting a specific attribute in the node then the `attributeName` parameter is required.
|
|
386
|
+
- `insertItemByIndex`: `(data: InsertItemType, index?: number, parent?: { path?: string, attributeName?: string }) => void` Adds an option based on the serial number and the path of the parent node.
|
|
387
|
+
- `getItemByPath`: `(path?: string, attributeName?: string) => void` Get the node that corresponds to the path `path`, or the `attributeName` parameter if it is a specific attribute in the node.
|
|
388
|
+
- `moveItemByPath`: `(from: { parent?: string, index: number }, to: { parent?: string, index?: number })` Swap options in the tree from one location to another.
|
|
389
|
+
- `setProperties`: `(data?: Partial<FormNodeProps>) => void` sets `properties`.
|
|
390
|
+
|
|
391
|
+
### Hooks
|
|
392
|
+
- `useSimpleFormRender()`: create `new SimpleFormRender()`.
|
|
393
|
+
- `useSimpleForm(defaultValues)`: create `new SimpleForm()`
|
|
394
|
+
|
|
395
|
+
## Other
|
|
396
|
+
|
|
397
|
+
### Properties structure description
|
|
398
|
+
Each item in the `properties` property is a form node, and the nodes are categorized into nested nodes and control nodes.
|
|
399
|
+
- Nested nodes.
|
|
400
|
+
Nodes that have a `properties` property that describes which component the node is, via the `type` and `props` fields, and do not carry a form field component (`Form.Item`).
|
|
401
|
+
- Node.
|
|
402
|
+
A node with no `properties` attribute that carries the form field component (`Form.Item`) by default.
|
|
403
|
+
```javascript
|
|
404
|
+
const properties = {
|
|
405
|
+
name3: {
|
|
406
|
+
// Nested nodes
|
|
407
|
+
// type: '',
|
|
408
|
+
// props: {},
|
|
409
|
+
properties: {
|
|
410
|
+
// Control node
|
|
411
|
+
first: {
|
|
412
|
+
label: 'first',
|
|
413
|
+
rules: [{ required: true, message: 'first empty' }],
|
|
414
|
+
type: 'Select',
|
|
415
|
+
props: {
|
|
416
|
+
style: { width: '100%' },
|
|
417
|
+
children: [{ type: 'Select.Option', props: { key: 1, value: '1', children: 'option1' } }]
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
},
|
|
422
|
+
}
|
|
423
|
+
```
|
|
424
|
+
- Form Node's types
|
|
425
|
+
```javascript
|
|
426
|
+
export interface FormComponent {
|
|
427
|
+
type?: string;
|
|
428
|
+
props?: any & { children?: any | Array<FormComponent> };
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
export type UnionComponent<P> =
|
|
432
|
+
| React.ComponentType<P>
|
|
433
|
+
| React.ForwardRefExoticComponent<P>
|
|
434
|
+
| React.FC<P>
|
|
435
|
+
| keyof React.ReactHTML;
|
|
436
|
+
|
|
437
|
+
// Component
|
|
438
|
+
export type CustomUnionType = FormComponent | Array<FormComponent> | UnionComponent<any> | Function | ReactNode
|
|
439
|
+
// FormRender's properties
|
|
440
|
+
export type PropertiesData = { [name: string]: FormNodeProps } | FormNodeProps[]
|
|
441
|
+
// field's props(String expressions after compilation)
|
|
442
|
+
export type GenerateFormNodeProps<T = {}> = FormComponent & FormItemProps & T & {
|
|
443
|
+
ignore?: boolean; // Mark the current node as a non-form node
|
|
444
|
+
inside?: CustomUnionType; // Nested components within nodes
|
|
445
|
+
outside?: CustomUnionType; // Nested components in the outer layer of the node
|
|
446
|
+
readOnly?: boolean; // read-only mode
|
|
447
|
+
readOnlyRender?: CustomUnionType; // Read-only mode rendering
|
|
448
|
+
typeRender?: CustomUnionType; // Registering components for custom rendering
|
|
449
|
+
properties?: PropertiesData;
|
|
450
|
+
hidden?: boolean;
|
|
451
|
+
}
|
|
452
|
+
// field's props(String expressions before compilation)
|
|
453
|
+
export type FormNodeProps = {
|
|
454
|
+
[key in keyof GenerateFormNodeProps]: key extends 'rules' ?
|
|
455
|
+
(string | Array<{ [key in keyof FormRule]: FormRule[key] | string }> | GenerateFormNodeProps[key])
|
|
456
|
+
: (key extends 'properties' ? GenerateFormNodeProps[key] : (string | GenerateFormNodeProps[key]))
|
|
457
|
+
}
|
|
458
|
+
```
|
|
459
|
+
### parameter injection
|
|
460
|
+
- The properties of the form node are set globally:
|
|
461
|
+
```javascript
|
|
462
|
+
|
|
463
|
+
<FormRender
|
|
464
|
+
options={{
|
|
465
|
+
layout: 'vertical',
|
|
466
|
+
props: { disabled: true }
|
|
467
|
+
}}
|
|
468
|
+
/>
|
|
469
|
+
```
|
|
470
|
+
|
|
471
|
+
- Parameters received by the registration component of the form:
|
|
472
|
+
```javascript
|
|
473
|
+
export interface GenerateParams<T = {}> {
|
|
474
|
+
name?: string;
|
|
475
|
+
path?: string;
|
|
476
|
+
field?: GenerateFormNodeProps<T>;
|
|
477
|
+
parent?: { name?: string; path?: string, field?: GenerateFormNodeProps<T>; };
|
|
478
|
+
formrender?: SimpleFormRender;
|
|
479
|
+
form?: SimpleForm;
|
|
480
|
+
};
|
|
481
|
+
```
|
|
482
|
+
### Path path rules involved in forms
|
|
483
|
+
Forms are allowed to be nested, so the form involves looking for a certain property. The paths follow certain rules
|
|
484
|
+
Example:
|
|
485
|
+
- `a[0]` denotes the first option below the array `a`
|
|
486
|
+
- `a.b` denotes the `b` attribute of the `a` object
|
|
487
|
+
- `a[0].b` represents the `b` attribute of the first option below the array `a`
|
|
488
|
+
|
|
489
|
+
### String Expression Usage
|
|
490
|
+
Property fields in a form node can support string expressions for linkage, except for `properties`.
|
|
491
|
+
1. Quick use: computational expressions wrapping target attribute values in `{{` and `}}`
|
|
492
|
+
```javascript
|
|
493
|
+
const properties = {
|
|
494
|
+
name1: {
|
|
495
|
+
label: 'name1',
|
|
496
|
+
valueProp: 'checked',
|
|
497
|
+
initialValue: true,
|
|
498
|
+
type: 'Checkbox',
|
|
499
|
+
props: {
|
|
500
|
+
children: 'option'
|
|
501
|
+
}
|
|
502
|
+
},
|
|
503
|
+
name2: {
|
|
504
|
+
label: "name2",
|
|
505
|
+
rules: '{{[{ required: formvalues && formvalues.name1 === true, message: "name2 empty" }]}}',
|
|
506
|
+
initialValue: 1,
|
|
507
|
+
type: 'Input',
|
|
508
|
+
props: {}
|
|
509
|
+
},
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
// OR
|
|
513
|
+
|
|
514
|
+
const properties = {
|
|
515
|
+
name1: {
|
|
516
|
+
label: 'name1',
|
|
517
|
+
valueProp: 'checked',
|
|
518
|
+
initialValue: true,
|
|
519
|
+
type: 'Checkbox',
|
|
520
|
+
props: {
|
|
521
|
+
children: 'option'
|
|
522
|
+
}
|
|
523
|
+
},
|
|
524
|
+
name2: {
|
|
525
|
+
label: "name2",
|
|
526
|
+
hidden: '{{formvalues && formvalues.name1 === true}}',
|
|
527
|
+
initialValue: 1,
|
|
528
|
+
type: 'Input',
|
|
529
|
+
props: {}
|
|
530
|
+
},
|
|
531
|
+
}
|
|
532
|
+
```
|
|
533
|
+
2. Rules for the use of string expressions
|
|
534
|
+
- A string has and can have only one pair of `{{` and `}}`.
|
|
535
|
+
- In addition to the three built-in variables (`form` (i.e., `useSimpleForm()`), `formrender` (i.e., `useSimpleFormRender()`), `formvalues`)), you can introduce an external variable via `plugins` and then reference the variable name directly in the string expression. in a string expression.
|
|
536
|
+
```javascript
|
|
537
|
+
import dayjs from 'dayjs';
|
|
538
|
+
import FormRender from "./form-render";
|
|
539
|
+
|
|
540
|
+
const properties = {
|
|
541
|
+
name3: {
|
|
542
|
+
label: "name3",
|
|
543
|
+
initialValue: "{{dayjs().format('YYYY-MM-DD')}}",
|
|
544
|
+
type: 'Input',
|
|
545
|
+
props: {}
|
|
546
|
+
},
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
<FormRender properties={properties} plugins={{ dayjs }} />
|
|
551
550
|
```
|