Home > database >  Dynamic form returns the same value for the first and second input
Dynamic form returns the same value for the first and second input

Time:02-25

I'm creating a custom dynamic form using Material UI enter image description here

As we can see that the dynamic form component starts only with one delivery point form. We could add another delivery point form by clicking the "Add Delivery" button. Here is the example after clicking the "Add Delivery" button.

enter image description here

The problem is: the first form and the second form have the same values (if there are more than 1 form) after we gave input to one of the first or second forms as seen in the screenshot below. This is not the condition I want.

enter image description here

But the rest (third, fourth, and so on) forms are unique as seen in the screenshot below. This is the condition I want.

enter image description here

Here is the simple working code:

DeliveryPoint.jsx

const DeliveryPoint = (props) => {
  const {
    initialFormObject,
    formObject,
    setFormObject,
    collapseObject,
    setCollapseObject
  } = props;

  const classes = useStyles();

  const deliveryPointBaseObject = initialFormObject.deliveryPointList[0];

  const handleFormObjectChange = (inputEvent, inputIndex) => {
    let deliveryPointListData = [...formObject.deliveryPointList];
    deliveryPointListData[inputIndex][inputEvent.target.name] =
      inputEvent.target.value;

    setFormObject((current) => ({
      ...current,
      deliveryPointList: deliveryPointListData
    }));
  };

  const handleDatePickerChange = (inputNewValue, inputIndex) => {
    let deliveryPointListData = [...formObject.deliveryPointList];
    deliveryPointListData[inputIndex].deliveryDate = inputNewValue;

    setFormObject((current) => ({
      ...current,
      deliveryPointList: deliveryPointListData
    }));
  };

  const handleCollapseChange = (inputIndex) => {
    let deliveryPointListData = [...collapseObject.deliveryPointList];
    deliveryPointListData[inputIndex] = !deliveryPointListData[inputIndex];

    setCollapseObject((current) => ({
      ...current,
      deliveryPointList: deliveryPointListData
    }));
  };

  const handleAddFormItemButtonClick = () => {
    let deliveryPointListData = [...formObject.deliveryPointList];
    deliveryPointListData.push(deliveryPointBaseObject);

    setFormObject((current) => ({
      ...current,
      deliveryPointList: deliveryPointListData
    }));

    deliveryPointListData = [...collapseObject.deliveryPointList];
    deliveryPointListData.push(false);

    setCollapseObject((current) => ({
      ...current,
      deliveryPointList: deliveryPointListData
    }));
  };

  const handleDeleteFormItemButtonClick = (inputIndex) => {
    let deliveryPointListData = [...formObject.deliveryPointList];
    deliveryPointListData.splice(inputIndex, 1);

    setFormObject((current) => ({
      ...current,
      deliveryPointList: deliveryPointListData
    }));

    deliveryPointListData = [...collapseObject.deliveryPointList];
    deliveryPointListData.splice(inputIndex, 1);

    setCollapseObject((current) => ({
      ...current,
      deliveryPointList: deliveryPointListData
    }));
  };

  return (
    <>
      {formObject.deliveryPointList.map((item, index) => (
        <Box key={index} className={classes.formItemContainer}>
          <Box className={classes.formItemTitleContainer}>
            {/* TITLE */}
            <Typography variant="h6">
              {index === 0 ? `Delivery point` : `#${index   1} Delivery point`}
            </Typography>

            {/* ADD OR DELETE BUTTON */}
            {index === 0 ? (
              <Button
                className={classes.formItemTitleButton}
                variant="outlined"
                startIcon={<IconAdd />}
                onClick={handleAddFormItemButtonClick}
              >
                Add Delivery
              </Button>
            ) : (
              <Button
                className={classes.formItemTitleButton}
                variant="outlined"
                startIcon={<IconRemove />}
                color="error"
                onClick={() => handleDeleteFormItemButtonClick(index)}
              >
                Remove Delivery
              </Button>
            )}
          </Box>

          {/* CONSIGNEE */}
          <FormControl
            required
            variant="outlined"
            className={classes.formItemInput}
          >
            <InputLabel>Consignee</InputLabel>

            <OutlinedInput
              label="Consignee"
              type="text"
              name="consignee"
              value={item.consignee}
              onChange={(event) => handleFormObjectChange(event, index)}
            />

            <FormHelperText>
              Search for name, street, city, or state by typing in the box.
            </FormHelperText>
          </FormControl>

          {/* DELIVERY DATE */}
          <LocalizationProvider dateAdapter={AdapterDateFns}>
            <DatePicker
              disableFuture
              label="Select Delivery Date"
              openTo="year"
              views={["year", "month", "day"]}
              value={item.deliveryDate}
              onChange={(newValue) => handleDatePickerChange(newValue, index)}
              renderInput={(params) => (
                <TextField
                  required
                  className={classes.formItemInput}
                  {...params}
                />
              )}
            />
          </LocalizationProvider>

          {/* COLLAPSE */}
          <Collapse
            in={collapseObject.deliveryPointList[index]}
            timeout="auto"
            unmountOnExit
            className={classes.formItemCollapse}
          >
            {/* DELIVERY INSTRUCTION */}
            <FormControl variant="outlined" className={classes.formItemInput}>
              <InputLabel>Delivery Instructions</InputLabel>

              <OutlinedInput
                label="Delivery Instructions"
                type="text"
                name="deliveryInstruction"
                value={item.deliveryInstruction}
                onChange={(event) => handleFormObjectChange(event, index)}
              />
            </FormControl>
          </Collapse>

          {/* EXPAND BUTTON */}
          <Button
            variant="contained"
            disableElevation
            startIcon={
              collapseObject.deliveryPoint ? (
                <IconArrowDropUp />
              ) : (
                <IconArrowDropDown />
              )
            }
            className={classes.formItemButtonExpand}
            onClick={() => handleCollapseChange(index)}
          >
            {collapseObject.deliveryPoint
              ? "Hide full data entry"
              : "Fill in more complete data?"}
          </Button>
        </Box>
      ))}
    </>
  );
};

export default DeliveryPoint;

App.jsx

const App = () => {
  const classes = useStyles();

  const initialFormObject = {
    // DELIVERY POINT
    deliveryPointList: [
      {
        consignee: "",
        deliveryDate: new Date(),
        deliveryInstruction: ""
      }
    ]
    // OTHER OBJECT ITEMS HERE
  };

  const initialCollapseObject = {
    deliveryPointList: [false]
    // OTHER LIST ITEMS HERE
  };

  const [formObject, setFormObject] = useState(initialFormObject);
  const [collapseObject, setCollapseObject] = useState(initialCollapseObject);

  return (
    <Box className={classes.pageRoot}>
      {/* FORM */}
      <Box className={classes.formContainer}>
        {/* DELIVERY POINT */}
        <DeliveryPoint
          initialFormObject={initialFormObject}
          formObject={formObject}
          setFormObject={setFormObject}
          collapseObject={collapseObject}
          setCollapseObject={setCollapseObject}
        />
      </Box>
    </Box>
  );
};

export default App;

Here is the full demo Edit dynamic-form-returns-the-same-value-for-the-first-and-second-input

CodePudding user response:

You are not making a copy of deliveryPointBaseObject. But, repeating it. Hence, you are getting the same value for first 2. Changing it to below one corrects your mutation issue.

const deliveryPointBaseObject = {...initialFormObject.deliveryPointList[0]};

  • Related