skip to Main Content

I have a NextJS app where I have this form:

<form id='roles-form' action='#' onSubmit={handleSubmit}>
  <ul className='h-56 overflow-y-auto p-3'>
    {roles.role.map((role) => {
      return (
        <li key={role.roleId}>
          <div className='flex rounded p-3 hover:bg-gray-100'>
            <label className='relative inline-flex w-full cursor-pointer items-center'>
              <input
                type='checkbox'
                name='roles'
                value={role.roleId}
                onChange={(event) => {
                  toast.info(event.target.value);
                }}
                className='peer sr-only'
              />
              <div className="peer h-5 w-9 rounded-full bg-gray-200 after:absolute after:left-[2px] after:top-[2px] after:h-4 after:w-4 after:rounded-full after:border after:border-gray-300 after:bg-white after:transition-all after:content-[''] peer-checked:bg-primary-600 peer-checked:after:translate-x-full peer-checked:after:border-white peer-focus:outline-none peer-focus:ring-4 peer-focus:ring-primary-300"></div>
              <span className='ml-3 text-sm font-medium text-gray-900'>{role.name}</span>
            </label>
          </div>
        </li>
      );
    })}
  </ul>
  <button
    type='submit'
    className='block w-full rounded-b-lg bg-gray-50 py-3 text-center text-sm font-medium text-gray-900 hover:bg-gray-100'>
    <div className='inline-flex items-center '>Assign</div>
  </button>
</form>

Basically it’s just a form with a bunch of checkboxes for whatever roles are to be assigned to a user.

Once I submit the form, I don’t know how to grab the values and get the checked checkboxes. I didn’t try to do this with useState because the list of roles are dynamic and it made it sound complicated so instead of tracking the state of the checkboxes, I just try to grab them on submit.

const handleSubmit = (event: FormEvent<HTMLFormElement>) => {
  event.preventDefault();

  const form = document.getElementById('roles-form') as HTMLFormElement;
  const formData = new FormData(form);

  console.log(event.target);
  console.log(formData);
};

2

Answers


  1. Use the change events on the checkboxes to update the component’s state and access it in handleSubmit:

    const [checkedState, setCheckedState] = useState({});
    ...
    onChange={(event) => {
      setCheckedState((state) => ({ ...state, [role.roleId]: event.target.checked
      ...
    }}
    ...
    const handleSubmit = (event) => {
      console.log(checkedState);
    }
    
    Login or Signup to reply.
  2. You can grab the values from formData using the entries or get function on it. If you want to get all values against a key, use getAll. See Mdn doc about formData for more details.

    You can adjust your handleSubmit function like this:

    const handleSubmit = (event: FormEvent<HTMLFormElement>) => {
      event.preventDefault();
    
      const form = event.currentTarget;
      const formData = new FormData(form);
      const checkedRoles = formData.getAll('roles');
      console.log(checkedRoles); // ['1', '2', '3', ...]
    };
    

    Having said that, now that you are working with React, I would suggest you do it the React way, which is by using state. Your form will work correctly, but it is not reactive to user interaction, which really is the whole point of React. Say tomorrow, your requirements change and now you have to show a tick icon only alongside the checkboxes which have been checked. It will become very difficult without using state. You can manage the form easily using useState like this:

    const [checkedRoles, setCheckedRoles] = useState([]); // no roles are checked initially
    
    const handleOnChange = (roleId, isChecked) => {
       if (isChecked) {
          setCheckedRoles((prev) => [...prev, roleId])
       } else {
          setCheckedRoles((prev) => prev.filter(r => r !== roleId))
       }
    }
    
    const handleSubmit = (event: FormEvent<HTMLFormElement>) => {
      event.preventDefault();
    
      console.log(checkedRoles); // ['1', '2', '3', ...]
    };
    
    <input
       type='checkbox'
       name='roles'
       value={role.roleId}
       onChange={(event) => {
          toast.info(event.target.value);
          handleOnChange(role.roleId, event.target.checked)
       }}
       className='peer sr-only'
    />
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search