Nested components
Form Builder supports nested components out of the box. There are two types of nested components:
- Simple nested components.
- Templates.
Simple nested components
Simple nested component is a React component, that binds to one of the component property.
For example your have your React component, where one of the properties described as
the node. The children
property is also treated as a node
property. A
component that is specified in the node
property is considered a nested component.
Templates
A template is simply a form within another form. The template is treated as a normal component, but with some features:
- The FormViewer component is used to display the template.
- The data inside the template is isolated from the parent form.
- Data can be transferred to the parent form as a nested object, or as a part of the parent form (regulated by the "Store data in parent form" flag).
Slots
Each component property defined as a node
property is treated as a slot where child components can be added. A component can have any
number of slots to which child components can be added.
As an example, let's see how the Message component from the React Suite library is described in Form Builder:
import {boolean, define, node, oneOf} from '@react-form-builder/core'
import {Message} from 'rsuite'
export const rsMessage = define(Message)
.type('RsMessage')
.name('Message')
.props({
children: node,
closeable: boolean,
header: node,
type: oneOf('info', 'success', 'warning', 'error').default('info')
})
There are two component properties that are described as node
: children and header. You can use this component on our
public demo.
Here is a form with a Message component. The Input component is bound to the header
slot, and the Button component is bound to
the children
slot. Note that if the slot is named children
, the slot name will be missing in the JSON with the form, because children
is the default slot name.
{
"version": "1",
"form": {
"key": "Screen",
"type": "Screen",
"props": {},
"children": [
{
"key": "RsMessage 1",
"type": "RsMessage",
"props": {},
"children": [
{
"key": "RsInput 1",
"type": "RsInput",
"props": {},
"slot": "header"
},
{
"key": "RsButton 1",
"type": "RsButton",
"props": {}
}
]
}
]
}
}
This is roughly what the form looks like in the screenshot below. In the components tree on the left, you can see that the Input and Button components are children of the Message component.
How it works
When rendering a component, the Form Builder first calculates all the properties of the component. After that, all child components are
calculated and bound to the component properties by the slot name specified in the child component. If there is no slot name, the default
slot, children
, is used.