Dynamic Fields
Field configurations can be dynamic, based on previously entered data. Here are a few examples:
<Form
config={{
fields: (data) => {
return [
{
id: "field1",
label: "Field 1",
type: "text"
},
{
id: "field2",
label: "Field 2",
secondaryText: "This field is only required if Field 1 is populated. Add something to the first field to see this field getting required.",
type: "text",
isRequired: data.field1
},
{
id: "field3",
label: "Field 3",
type: "text"
},
{
id: "field4",
label: "Field 4",
secondaryText: "This field is only enabled if Field 3 is populated.",
type: "text",
isDisabled: !data.field3
},
{
id: "name",
label: "Name",
type: "text",
isRequired: true
},
{
id: "age",
label: data.name ? `What is the age of ${data.name}?` : "Age",
secondaryText: "The label of this field is dynamic.",
type: "number"
}
]
}
}}
...
/>
You can do the same in the render function, for example if you want to hide a group of fields if a checkbox above isn't checked:
<Form
render={({ fieldProps }) => (
<div>
{fieldProps.fields.myCheckbox}
<br />
{fieldProps.data.myCheckbox ? (
<div>
{fieldProps.fields.groupField1}
<br />
{fieldProps.fields.groupField2}
...
</div>
) : null}
</div>
)}
...
/>
However, be careful to not make a form to dynamic, this can be irritating for the user and hard to test.
Function Props
For even more dynamicness, Stages has now support for function props. Basically you can turn any configuration property
into a function property by adding Fn
to it. For example you can turn the property label
into a function property by
naming it labelFn
. This works for all non reserved props. Here's an example:
{
id: "email",
labelFn: ({ fieldData }) => {
if (fieldData && fieldData.indexOf('@') > -1 && fieldData.indexOf('.') > -1) {
return "Email 😎";
}
if (fieldData && (fieldData.indexOf('@') === -1 || fieldData.indexOf('.') === -1)) {
return "Email 🤕";
}
return "Email";
},
type: "email",
isRequired: true
}
What we do here is render a different emoticon in the label based on the validity of the entered email.
In all function props, you have access to the following data:
- path: The fields path
- fieldData: The current field data
- alldata: All the forms data
- interfaceState: The forms interface state
The isRendered prop
To help with dynamic fields, we've added the isRendered
property. An example:
...
{
id: "myfield",
label: "My Field",
type: "text",
isRendered: (path, data, allData) => {
if (path.includes("[1]")) return false;
return true;
}
},
...
This field only renders, if it's in a collection and has an index of 1
, so in other words, if it is the second item
in a collection. All other items in the collection will not render this field.