Skip to content

Commit

Permalink
Update examples/dynamic_fields.md
Browse files Browse the repository at this point in the history
  • Loading branch information
sebelga committed Oct 6, 2020
1 parent e3dcf1b commit 869267e
Showing 1 changed file with 33 additions and 38 deletions.
Expand Up @@ -6,45 +6,42 @@ sidebar_label: Dynamic fields

## Basic

Dynamic fields are fields that the user can add or remove in your form. Those fields will end up in an array of _values_ or an array of _objects_.
Dynamic fields are fields that the user can add or remove in your form. Those fields will end up in an array of _values_ or an array of _objects_. To enable dynamic fields in your form you use [the `<UseArray />` component](../core/use_array).

Let's imagine a form that lets a user enter multiple parent / child relationships.

```js
export const DynamicFields = () => {
const fetchedData = {
name: 'My resource',
relationships: [
const todoList = {
items: [
{
parent: 'Parent 1',
child: 'Child 1',
title: 'Title 1',
subTitle: 'Subtitle 1',
},
{
parent: 'Parent 2',
child: 'Child 2',
title: 'Title 2',
subTitle: 'Subtitle 2',
},
],
};
const { form } = useForm({ defaultValue: fetchedData });
const { form } = useForm({ defaultValue: todoList });

const submitForm = () => {
console.log(form.getFormData());
};

return (
<Form form={form}>
<UseField path="name" config={{ label: 'Name' }} component={TextField} />
<EuiSpacer />
<UseArray path="relationships">
<UseArray path="items">
{({ items, addItem, removeItem }) => {
return (
<>
{items.map((item) => (
<EuiFlexGroup key={item.id}>
<EuiFlexItem>
<UseField
path={`${item.path}.parent`}
config={{ label: 'Parent' }}
path={`${item.path}.title`}
config={{ label: 'Title' }}
component={TextField}
// Make sure to add this prop otherwise when you delete
// a row and add a new one, the stale values will appear
Expand All @@ -53,8 +50,8 @@ export const DynamicFields = () => {
</EuiFlexItem>
<EuiFlexItem>
<UseField
path={`${item.path}.child`}
config={{ label: 'Child' }}
path={`${item.path}.subTitle`}
config={{ label: 'Subtitle' }}
component={TextField}
readDefaultValueOnForm={!item.isNew}
/>
Expand All @@ -71,7 +68,7 @@ export const DynamicFields = () => {
</EuiFlexGroup>
))}
<EuiButtonEmpty iconType="plusInCircle" onClick={addItem}>
Add relationship
Add item
</EuiButtonEmpty>
<EuiSpacer />
</>
Expand All @@ -98,13 +95,12 @@ If you need to validate the number of items in the array, you can provide a `val
The first one is easy, let's look at the second option:

```js
const relationShipsValidations = [
const itemsValidations = [
{
validator: ({ value }: { value: any[] }) => {
// "value" correspond to the "items" passed to the children func below
if (value.length === 0) {
return {
message: 'You need to add at least one relationship',
message: 'You need to add at least one item',
};
}
},
Expand All @@ -127,28 +123,26 @@ export const DynamicFieldsValidation = () => {

return (
<Form form={form}>
<UseField path="name" config={{ label: 'Name' }} component={TextField} />
<EuiSpacer />
<UseArray path="relationships" validations={relationShipsValidations}>
<UseArray path="items" validations={itemsValidations}>
{({ items, addItem, removeItem, error, form: { isSubmitted } }) => {
const isInvalid = error !== null && isSubmitted;
return (
<>
<EuiFormRow label="Relationships" error={error} isInvalid={isInvalid} fullWidth>
<EuiFormRow label="Todo items" error={error} isInvalid={isInvalid} fullWidth>
<>
{items.map((item) => (
<EuiFlexGroup key={item.id}>
<EuiFlexItem>
<UseField
path={`${item.path}.parent`}
config={{ label: 'Parent', validations: textFieldValidations }}
path={`${item.path}.title`}
config={{ label: 'Title', validations: textFieldValidations }}
component={TextField}
/>
</EuiFlexItem>
<EuiFlexItem>
<UseField
path={`${item.path}.child`}
config={{ label: 'Child', validations: textFieldValidations }}
path={`${item.path}.subtitle`}
config={{ label: 'Subtitle', validations: textFieldValidations }}
component={TextField}
/>
</EuiFlexItem>
Expand All @@ -166,7 +160,7 @@ export const DynamicFieldsValidation = () => {
</>
</EuiFormRow>
<EuiButtonEmpty iconType="plusInCircle" onClick={addItem}>
Add relationship
Add item
</EuiButtonEmpty>
<EuiSpacer />
</>
Expand Down Expand Up @@ -196,9 +190,7 @@ export const DynamicFieldsReorder = () => {

return (
<Form form={form}>
<UseField path="name" config={{ label: 'Name' }} component={TextField} />
<EuiSpacer />
<UseArray path="relationships">
<UseArray path="items">
{({ items, addItem, removeItem, moveItem }) => {
const onDragEnd = ({ source, destination }: DropResult) => {
if (source && destination) {
Expand All @@ -208,7 +200,7 @@ export const DynamicFieldsReorder = () => {

return (
<>
<EuiFormRow label="Relationships" fullWidth>
<EuiFormRow label="Todo items" fullWidth>
<EuiDragDropContext onDragEnd={onDragEnd}>
<EuiDroppable droppableId="1">
{items.map((item, idx) => {
Expand All @@ -229,15 +221,18 @@ export const DynamicFieldsReorder = () => {
</EuiFlexItem>
<EuiFlexItem>
<UseField
path={`${item.path}.parent`}
config={{ label: 'Parent' }}
path={`${item.path}.title`}
config={{ label: 'Title', validations: textFieldValidations }}
component={TextField}
/>
</EuiFlexItem>
<EuiFlexItem>
<UseField
path={`${item.path}.child`}
config={{ label: 'Child' }}
path={`${item.path}.subtitle`}
config={{
label: 'Subtitle',
validations: textFieldValidations,
}}
component={TextField}
/>
</EuiFlexItem>
Expand All @@ -260,7 +255,7 @@ export const DynamicFieldsReorder = () => {
</EuiDragDropContext>
</EuiFormRow>
<EuiButtonEmpty iconType="plusInCircle" onClick={addItem}>
Add relationship
Add item
</EuiButtonEmpty>
<EuiSpacer />
</>
Expand Down

0 comments on commit 869267e

Please sign in to comment.