Home > Back-end >  add or remove a string from an array based on a checkbox - nextjs, react, typescript, firestore, fir
add or remove a string from an array based on a checkbox - nextjs, react, typescript, firestore, fir

Time:08-18

i have a nextjs (using typescript) front end. I am attempting to create a user creation form where an administrator can create additional users. the goal is for the form to generate a simple user state object that will then be passed into a create user document function. The user object is incredibly simple. below:

const user = {
  name: "",
  email: "",
  roles: []

}

the roles are what is giving me a headache. I am attempting to use Chakra UI checkboxes to add or remove strings from the roles array

<CheckboxGroup colorScheme="green">
                <Stack spacing={[1, 5]} direction={["column", "row"]}>
                  <Text>roles</Text>
                  <Checkbox
                    value="admin"
                    id="admin"
                    name="admin"
                    onChange={handleCheckBoxChange}
                  >
                    admin
                  </Checkbox>
                  <Checkbox
                    value="user"
                    id="user"
                    name="user"
                    onChange={handleCheckBoxChange}
                  >
                    user
                  </Checkbox>
                </Stack>
              </CheckboxGroup>

I've managed to get the checkbox to toggle to assign a boolean to the the name of each checkbox, but that obviously doesn't do me much good.

here is my handleCheckBoxChange function


  const handleCheckBoxChange = (e: any) => {
    const target = e.target;
    const value = target.type === "checkbox" ? target.checked : target.value;
    const name = target.name;
    setRoles({ [name]: value });
    console.log(roles);
  };

literally all i want is for when the admin box is checked for the string 'admin' to be added to the roles away. when it's unchecked i want it removed. same for the user box.

likely this is an easy fix and i've just been staring at it too long

lmk


added pictures

no roles checked - nothing in the array

admin checked, nothing in the array

admin and user checked, array shows 'admin'

user checked, array shows 'user'

both checked, array shows 'admin'


heres my entire code block - i am rendering this form inside a chakra ui popup modal

import {
  Button,
  Checkbox,
  CheckboxGroup,
  Input,
  Modal,
  ModalBody,
  ModalCloseButton,
  ModalContent,
  ModalFooter,
  ModalHeader,
  ModalOverlay,
  Stack,
  Text,
  useDisclosure,
} from "@chakra-ui/react";
import { useRouter } from "next/router";
import React, { useState } from "react";
import { addUser } from "../../lib/firebase";

export default function AddUser() {
  const initialRef = React.useRef(null);
  const finalRef = React.useRef(null);
  const { isOpen, onOpen, onClose } = useDisclosure();

  const router = useRouter();
  const customer = router.query.customer;
  const [roles, setRoles] = useState<string[]>([]);

  const [user, setUser] = useState({});

  const handleInputChange = (e: any) => {
    const { name, value } = e.target;
    setUser({ ...user, [name]: value });
  };

  const handleCheckBoxChange = (e: any) => {
    const target = e.target;
    const name = target.name;
    setRoles((currentRoles) =>
      target.checked
        ? [...currentRoles, name]
        : currentRoles.filter((role) => role != name)
    );
    setUser({ ...user, roles: roles });
  };

  const handleSubmit = () => {
    addUser(customer, user);
    onClose();
  };

  console.log(user);

  return (
    <>
      <Button onClick={onOpen}>add user</Button>

      <Modal
        isOpen={isOpen}
        onClose={() => {
          onClose();
          setUser([]);
        }}
        initialFocusRef={initialRef}
        finalFocusRef={finalRef}
      >
        <ModalOverlay />
        <ModalContent>
          <ModalHeader>Modal Title</ModalHeader>
          <ModalCloseButton />
          <ModalBody>
            <form onSubmit={handleSubmit}>
              <Input
                ref={initialRef}
                name="name"
                placeholder="name"
                onChange={handleInputChange}
              />
              <Input
                name="email"
                placeholder="email"
                onChange={handleInputChange}
              />
              <CheckboxGroup colorScheme="green">
                <Stack spacing={[1, 5]} direction={["column", "row"]}>
                  <Text>roles</Text>
                  <Checkbox
                    name="admin"
                    value="admin"
                    onChange={handleCheckBoxChange}
                  >
                    admin
                  </Checkbox>
                  <Checkbox
                    name="user"
                    value="user"
                    onChange={handleCheckBoxChange}
                  >
                    user
                  </Checkbox>
                </Stack>
              </CheckboxGroup>
            </form>
          </ModalBody>

          <ModalFooter>
            <Button
              colorScheme="blue"
              mr={3}
              type="submit"
              onClick={handleSubmit}
            >
              submit
            </Button>
          </ModalFooter>
        </ModalContent>
      </Modal>
    </>
  );
}

CodePudding user response:

One option would be to just update the state based on the name like you are, but passing a function to the state setter that handles adding/removing the item, i.e.:

const handleCheckBoxChange = (e: any) => {
  const target = e.target;
  const name = target.name;
  setRoles((currentRoles) =>
    target.checked
      ? [...currentRoles, name]
      : currentRoles.filter((role) => role !== name)
  );
};

When passing a function to a state setter, the function will be passed the existing state and is expected to return the updated state. In this way, you will get the currently selected roles and either return a copy of it with the selected item added, or removed depending on if the checkbox is checked.

  • Related