Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Nested fieldarray in formik

I am using formik for the forms. In my form, I need to use the concept of FieldArray and it's a nested one. I could not fill the nested forms with respective values. Here is how I have done

const Itinerary = ({ itineraries, push, remove }) => {
  return (
    <>
      <Heading>Itinerary</Heading>
      {itineraries && itineraries.length === 0 && (
        <span
          style={{
            color: theme.color.primary,
            padding: "0 10px",
            cursor: "pointer"
          }}
          onClick={() => push({})}
        >
          +
        </span>
      )}
      {itineraries &&
        itineraries.length > 0 &&
        itineraries.map((day, index) => {
          return (
            <React.Fragment key={index}>
              <Row key={index} style={{ alignItems: "center" }}>
                <Text>
                  How many
                  <DaysField
                    component={TextField}
                    name={`itineraries.${index}.days`}
                    placeholder="days"
                    normalize={val => val && parseInt(val)}
                  />
                  of itinerary?
                </Text>
                {itineraries && itineraries.length - 1 === index && (
                  <>
                      <Button>
                        <Button.Round onClick={() => push({})}>+</Button.Round>
                      </Button>
                      <Button>
                        <Button.Round onClick={() => remove(index)}>
                          -
                        </Button.Round>
                      </Button>
                  </>
                )}
              </Row>
              <FieldArray
                name={`itineraries.${index}.itinerary`}
                render={({ push, remove }) => (
                  <>
                    <Heading>
                      Fill up itinerary
                      {itineraries[index].itinerary &&
                        itineraries[index].itinerary.length === 0 && (
                          <span
                            style={{
                              color: theme.color.primary,
                              padding: "0 10px",
                              cursor: "pointer"
                            }}
                            onClick={() => push({})}
                          >
                            +
                          </span>
                        )}
                    </Heading>
                    {itineraries[index].itinerary &&
                      itineraries[index].itinerary.length > 0 &&
                      itineraries[index].itinerary.map((i, idx) => {
                        console.log(
                          "itinerary index",
                          itineraries[index].itinerary[idx]
                        );
                        return (
                          <React.Fragment>
                            <Row
                              style={{
                                alignItems: "center",
                                alignSelf: "center"
                              }}
                            >
                              <Col xs={12} md={3}>
                                <Field
                                  component={TextField}
                                  placeholder="Day"
                                  name={`${itineraries[index].itinerary[idx]}.day`}
                                />
                              </Col>
                              <Col xs={12} md={3}>
                                <Field
                                  component={TextField}
                                  placeholder="Description"
                                  name={`${itineraries[index].itinerary[idx]}.description`}
                                />
                              </Col>
                              <Col xs={12} md={3}>
                                <Field
                                  component={TextField}
                                  placeholder="Overnight"
                                  name={`${itineraries[index].itinerary[idx]}.overnight`}
                                />
                              </Col>
                              <Col xs={12} md={2}>
                                <Field
                                  component={TextField}
                                  placeholder="Altitude"
                                  name={`${itineraries[index].itinerary}.altitude`}
                                  normalize={value => {
                                    return value && parseFloat(value);
                                  }}
                                />
                              </Col>
                              <Col xs={12} md={1}>
                                {itineraries &&
                                  itineraries.length - 1 === index && (
                                    <>
                                      <ActionBtn>
                                        <Button>
                                          <Button.Round
                                            onClick={() => push({})}
                                          >
                                            +
                                          </Button.Round>
                                        </Button>
                                        <Button>
                                          <Button.Round
                                            onClick={() => remove(index)}
                                            color={theme.color.red}
                                          >
                                            -
                                          </Button.Round>
                                        </Button>
                                      </ActionBtn>
                                    </>
                                  )}
                              </Col>
                            </Row>
                          </React.Fragment>
                        );
                      })}
                  </>
                )}
              />
            </React.Fragment>
          );
        })}
    </>
  );
};

The itineraries initialValues looks like this

itineraries: [
                {
                  days: 1,
                  itinerary: [
                    {
                      day: "Day 1",
                      description: "description",
                      overnight: "overnight info",
                      altitude: 150.5
                    },
                    {
                      day: "Day 2",
                      description: "description 2",
                      overnight: "overnight info",
                      altitude: 150.5
                    }
                  ]
                }
              ]

Only Nested part is not working. Can anyone help me at this, please?

like image 597
Serenity Avatar asked Feb 03 '20 12:02

Serenity


Video Answer


1 Answers

You problem is in how you pass the name for the component

name={`${itineraries[index].itinerary[idx]}.overnight`}

This way, what you are doing is passing the value of itineraries[index].itinerary[idx] to a string.

What you should do is pass that as a string, not it's value.

name={`itineraries[${index}].itinerary[${idx}]}.overnight`}

This way, only the indexs get the value printed, which is correct.

Here is the difference

${itineraries[index].itinerary[idx]}.overnight will return [object Object].overnight because you are access the value of itineraries[index].itinerary[idx] and it's calling .toString().

But itineraries[${index}].itinerary[${idx}]}.overnight will return itineraries[0].itinerary[0].overnight which is a valid formik string and it can get it's value.

like image 167
Vencovsky Avatar answered Sep 25 '22 08:09

Vencovsky