4

I'm following this documentation to use FormDataConsumer to show / hide inputs. But I have a nested ArrayInput / FormDataConsumer as below:

export const MyClassCreate = ({ permissions, ...props }) => (
  <Create {...props}>
    <TabbedForm>
      <FormTab label="summary">
        <SelectInput source="className" choices={choices} optionText="choiceType"
                     optionValue="className"disableValue="not_available"
        />
        <TextInput source="field1" />
        <NumberInput source="field2" />
        <FormDataConsumer>
          {({ formData, ...rest }) =>
            formData.className === "my.package.MyClass2" && (
              <TextInput source="field3" {...rest} />
            )
          }
        </FormDataConsumer>
        <FormDataConsumer>
          {({ formData, ...rest }) =>
            formData.className === "my.package.MyClass1" && (
              <Fragment>
                <NumberInput source="field4" {...rest} />
                <ArrayInput source="arrayField1">
                  <SimpleFormIterator>
                    <SelectInput source="field5.subField6" choices={choices} 
                                 optionText="choiceType"
                                 optionValue="className" 
                                 disableValue="not_available"
                    />
                    <TextInput source="field5.subField7" />
                    <FormDataConsumer>
                      {({ formData, scopedFormData, getSource, ...rest }) =>
                        scopedFormData.field5 &&
                        scopedFormData.field5.subField8 &&
                        scopedFormData.field5.subField8 ===
                          "my.package.MyClass3" && (
                          <NumberInput
                            source={getSource("field5.subField9")}
                            {...rest}
                          />
                        )
                      }
                    </FormDataConsumer>
                    <FormDataConsumer>
                      {({ formData, scopedFormData, getSource, ...rest }) =>
                        scopedFormData.field5 &&
                        scopedFormData.field5.subField8 &&
                        scopedFormData.field5.subField8 ===
                          "my.package.MyClass4" && (
                          <ArrayInput source={getSource("reward.rewards")}>
                            <SimpleFormIterator>
                              <SelectInput source={getSource("problemField1")} choices={choices}
                                           optionText="choiceType" optionValue="className"
                                           disableValue="not_available"
                              />
                              <TextInput source={getSource("problemField2")} />
                              <FormDataConsumer>
                                {({
                                  formData,
                                  scopedFormData,
                                  getSource,
                                  ...rest
                                }) =>
                                  scopedFormData.field8 &&
                                  scopedFormData.field8 ===
                                    "my.package.MyClass5" && (
                                    <NumberInput
                                      source={getSource("field8")}
                                      {...rest}
                                    />
                                  )
                                }
                              </FormDataConsumer>
                            </SimpleFormIterator>
                          </ArrayInput>
                        )
                      }
                    </FormDataConsumer>
                  </SimpleFormIterator>
                </ArrayInput>
              </Fragment>
            )
          }
        </FormDataConsumer>
      </FormTab>
      <FormTab label="campaign">
        <DateInput source="startTime" parse={dateParser} />
        <DateInput source="expirationTime" parse={dateParser} />
      </FormTab>
    </TabbedForm>
  </Create>
);

My problem is that in problemField1 and problemField2, although I'm calling getSource like I'm supposed to, the actual resolution of the source is still using referring to the first level source dereferencing. Is there a way to tell my nested / inner getSource to point to the right "level"?

paulito415
  • 194
  • 1
  • 9

1 Answers1

1

I've been able to create nested ArrayInput with react-admin

Here's the simple example:

const NavBarInput = ({ source }) => (
  <Box>
    <ArrayInput source={source}>
      <SimpleFormIterator>
        <TextInput source="title" />
        <FormDataConsumer>
          {({ getSource }) => (
            <NavBarInput source={getSource?.('items')} />
          )}
        </FormDataConsumer>
      </SimpleFormIterator>
    </ArrayInput>
  </Box>
);
Igor Sukharev
  • 2,467
  • 24
  • 21
  • This actually works, thank you! Just for clarity: when you iterate through the inner nested array each input field's `source` can simply be the array element's property name. – chichilatte Sep 15 '21 at 12:37