Ruan Duarte
Ruan Duarte

Reputation: 385

Add input to the onclick event in react

I have a form made with formik, in which one of the information entered is the contact, however the user can have more than one contact.

I want to add a button that when clicking, new fields for entering more contacts appear. I've tried some logic, but to no avail

const { getFieldProps, touched, errors, isValid, handleSubmit } = useFormik({
    initialValues: {
      phone_name: '',
      phone_ddd: '',
      phone_number: '',
      phone_observation: ''
    },
    onSubmit: (values, actions) => {
      saveOrganization({
        variables: {
          name: values.phone_name,
          ddd: values.phone_ddd,
          number: values.phone_number,
          observation: values.phone_observation,
        }
    })
})

return (
<TextField
  margin="dense"
  id="phone_name"
  label={<IntlMessages id="name" />}
  fullWidth
  {...getFieldProps("phone_name")}
/>
{touched.phone_name && errors.phone_name ? (
  <small>{errors.phone_name}</small>
) : null}
<InputMask
mask="99"
disabled={false}
maskChar=" "
{...getFieldProps("phone_ddd")}
>
{() =>
  <TextField
  label={<IntlMessages id='ddd' />}
  fullWidth
  {...getFieldProps("phone_ddd")}
  />
}
</InputMask>
{touched.phone_ddd && errors.phone_ddd ? (
  <small>{errors.phone_ddd}</small>
) : null}
<InputMask
mask="999999999"
disabled={false}
maskChar=" "
{...getFieldProps("phone_number")}
>
{() =>
<TextField
label={<IntlMessages id='number' />}
fullWidth
{...getFieldProps("phone_number")}
/>
}
</InputMask>
{touched.phone_number && errors.phone_number ? (
  <small>{errors.phone_number}</small>
) : null}

I want to add a button and new inputs appear

Upvotes: 1

Views: 1814

Answers (1)

This is my approach. First I declare initialValues to have field 'contact' as array like this

useFormik({
    initialValues: {
      contact: [
        {
          name: "",
          age: "",
        },
      ],
    },
  });

Then I create a function for adding new field

const handleNewField = () => {
    formik.setFieldValue("contact", [
      ...formik.values.contact,
      { name: "", age: "" },
    ]);
  };

And in the render just map it out from array like this

<form onSubmit={formik.handleSubmit}>
    {formik.values.contact.map((contact, index) => (
        <div key={index}>
            <label>Name</label>
            <input {...formik.getFieldProps(`contact[${index}].name`)} />
            <label>Age</label>
            <input {...formik.getFieldProps(`contact[${index}].age`)} />
        </div>
    ))}
    <button type="submit">Submit</button>
    <button type="button" onClick={handleNewField}>
        New Field
    </button>
  </form>

I have try this and this is work just fine for me. If you have any question feel free to ask me I'll try my best to answer


Final code look like this

import React from "react";
import { useFormik } from "formik";

function App() {
  const formik = useFormik({
    initialValues: {
      contact: [
        {
          name: "",
          age: "",
        },
      ],
    },
    onSubmit: (values) => {
      console.log(values);
    },
  });

  const handleNewField = () => {
    formik.setFieldValue("contact", [
      ...formik.values.contact,
      { name: "", age: "" },
    ]);
  };

  return (
    <div>
      <form onSubmit={formik.handleSubmit}>
        {formik.values.contact.map((contact, index) => (
          <div key={index}>
            <label>Name</label>
            <input {...formik.getFieldProps(`contact[${index}].name`)} />
            <label>Age</label>
            <input {...formik.getFieldProps(`contact[${index}].age`)} />
          </div>
        ))}
        <button type="submit">Submit</button>
        <button type="button" onClick={handleNewField}>
          New Field
        </button>
      </form>
    </div>
  );
}

export default App;

Upvotes: 3

Related Questions