Formik check all checkboxes - reactjs

The below code is checking the checkboxes one at a time each time select-all is clicked.
I've used the same code in SelectAllStudents elsewhere in my application not using Formik and it works fine. It processes each item in checkboxes.forEach but only checks the last item in the list on each click and I need to know how to get this to check all on a single click
const selectAllStudents = (contactType: string) => {
const checkboxes = document.querySelectorAll("#studentEmail");
var nativeInputValueSetter = Object?.getOwnPropertyDescriptor(
window.HTMLInputElement.prototype,
"checked"
)?.set;
checkboxes.forEach((checkbox) => {
nativeInputValueSetter?.call(checkbox, true);
let event = new Event("click", { bubbles: true })
checkbox.dispatchEvent(event);
});
})
this is the return markup from <StudentCheckBoxes / >
{students!.map((student, idx) => {
return (
<div key={idx+student.personId}>
<div className="inline-flex items-center">
<Field
type="checkbox"
className="w-4 h-4"
value={student.studentId.toString()}
name={"students"}
id={"studentEmail"}
/>
<span className="ml-2 text-sm">
{student.preferredName} {student.surname}
</span>
</div>
</div>
);
})}
Initial part of the form up to the select-all button
return (
<div>
<Formik
initialValues={initialValues}
onSubmit={onSubmit}
validateOnChange={true}
validationSchema={validationSchema}
className="text-gray-700"
>
{({ values, errors }) => (
<Form className="container pl-1 pr-3 pb-3 mx-auto">
{/* uncomment below to output form and error values */}
<pre>{JSON.stringify(values, null, 2)}</pre>
<pre>{JSON.stringify(errors, null, 2)}</pre>
<div className="flex-col text-center w-full mb-6 hidden 2xl:block">
<h1 className="sm:text-3xl text-2xl font-medium title-font mb-4 text-gray-900">
Email
</h1>
<p className="">Send E-Mail to Group</p>
</div>
{!loadingStudents && filteredStudents.length > 0 && (
<div className="grid grid-cols-2 mb-3">
<StudentCheckboxes students={students} contactType={contactType} />
</div>
)}
<div className="mb-2 ml-3 text-error-red error">
{errors.students}
</div>
<p onClick={() => selectAllStudents(contactType)} className="mb-4 text-sm underline cursor-pointer">Select All</p>

Related

reactjs remember me functionality on localstorage

I'm having a problem here when creating a remember me function in Reactjs.
So, I managed to enter the username, password and isChecked into localstorage.
However, when I logged out, all the data in the local storage was deleted including the username, password and isChecked.
How do you make the username, password and isChecked persist after logging out? Thank You
MyCode =
import React, { useState } from "react";
import Logo from "../../../../assets/images/logo.png";
import BackgroundProfile from "../../../../assets/images/background-profile.png";
import { VscKey } from "react-icons/vsc";
import { Link } from "react-router-dom";
import { signin } from "../../../../service/account";
import { toast } from "react-toastify";
export default function CardLogin(props) {
const {
labelText,
inputText,
loginType,
firstOptionLogin,
secondOptionLogin,
labelIcon,
firstRoute,
secondRoute,
firstIcon,
secondIcon,
} = props;
const [username, setUsername] = useState(() =>
localStorage.checkbox ? localStorage.username : ""
);
const [password, setPassword] = useState(() =>
localStorage.checkbox ? localStorage.password : ""
);
const [isChecked, setIsChecked] = useState(() => !!localStorage.checkbox);
const initialValue = {
username: username,
password: password,
nik: "",
};
const [isLoading, setIsLoading] = useState(false);
const handleSubmit = () => {
if (isChecked && username !== "") {
localStorage.username = username;
localStorage.password = password;
localStorage.checkbox = isChecked ? "1" : "";
}
const data = new URLSearchParams();
console.log(loginType);
if (loginType === "username") {
data.append("username", initialValue.username);
data.append("password", initialValue.password);
data.append("grant_type", "password");
}
setIsLoading(true);
signin(data, loginType)
.then((response) => {
if (response?.code === 200) {
console.log(response);
localStorage.setItem(
"accessToken",
JSON.stringify(response.data.accessToken)
);
localStorage.setItem(
"userSession",
JSON.stringify(response.data.accessTokenExpiresAt)
);
window.location.reload();
} else {
toast.error(response.message);
}
})
.catch((error) => {
console.log(error);
})
.finally(() => {
setIsLoading(false);
});
};
return (
<div
style={{
backgroundSize: "100% 75%",
backgroundRepeat: "no-repeat",
height: "100%",
backgroundImage: `url(${BackgroundProfile})`,
}}
>
{/* Button Back on The Top of Page */}
<button>
<div className="rounded-full w-5 md:w-10 h-5 md:h-10 p-3 relative top-2 left-2">
{/* <FaArrowLeft className="text-[#DD2729] text-xs md:text-base absolute top-1/2 left-1/2 -translate-y-1/2 -translate-x-1/2" /> */}
</div>
</button>
{/* Logo & Card Login */}
<img
src={Logo}
className="absolute top-6 bottom-6 right-4 w-2/5 md:w-1/5"
alt="Logo"
/>
<div className="mx-auto mt-8 w-3/5 md:w-2/5 bg-white px-5 py-3 md:px-8 md:py-5 rounded-md drop-shadow-xl">
<button>
{/* <FaArrowLeft className="text-[#DD2729] text-xs md:text-base" /> */}
</button>
<article
style={{ fontFamily: "ubuntu" }}
className="text-center text-[#808285] text-xs md:text-lg"
>
Selamat Datang! <br /> Silakan masuk untuk mulai menggunakan aplikasi
</article>
{/* Form Login*/}
<form onSubmit={handleSubmit} className="pt-3 md:pt-5">
<div>
<label
htmlFor={loginType}
className="text-[#424242] text-xs md:text-sm "
>
{labelText}
</label>
<div className="flex">
<div
className={`w-10 flex items-center justify-center bg-blue-lighter border-y border-l border-[#9E9E9E] rounded-l text-blue-dark`}
>
{labelIcon}
</div>
<input
id="username"
name="username"
type="text"
placeholder={inputText}
value={username}
onChange={(e) => setUsername(e.target.value)}
className={`w-full border-l-0 border-[#9E9E9E] rounded-r text-xs md:text-lg font-sans`}
/>
</div>
</div>
<div className="pt-2 md:pt-3">
<label
htmlFor="password"
className="text-[#424242] text-xs md:text-sm"
>
Password
</label>
<div className="flex">
<div
className={`w-10 flex items-center justify-center bg-blue-lighter border-y border-l border-[#9E9E9E] rounded-l text-blue-dark `}
>
<VscKey className="text-[#A8A8A8] text-xl" />
</div>
<input
id="password"
name="password"
type="password"
placeholder="Masukkan kata sandi anda"
value={password}
onChange={(e) => setPassword(e.target.value)}
className={`w-full border-l-0 border-[#9E9E9E] rounded-r text-xs md:text-lg font-normal `}
/>
</div>
</div>
{/* End of Form Login */}
{/* Remember me & Forgot Password */}
<div className="flex pt-3 items-center justify-between">
<div className="flex items-center gap-1.5">
<input
type="checkbox"
checked={isChecked}
name="lsRememberMe"
onChange={(e) => setIsChecked(e.target.checked)}
className="rounded"
/>
<label htmlFor="" className="text-xs md:text-sm">
Remember me
</label>
</div>
<div className="">
<Link
to="/forgot-password"
className="text-xs md:text-sm underline underline-offset-1 font-bold"
>
Forgot password
</Link>
</div>
</div>
<input
type="submit"
value={isLoading ? "Loading" : "Masuk"}
disabled={isLoading}
className="bg-[#EA001E] hover:bg-[#F55151] active:bg-[#BA0D0D] w-full text-white font-bold text-md rounded-lg p-2 mt-4 shadow-xl cursor-pointer text-xs md:text-sm"
/>
</form>
{/* End of Remember me & Forgot Password */}
{/* Login Option */}
<div className="mt-3">
<h4 className="login-selection text-center text-xs md:text-sm">
or login with
</h4>
</div>
<div className="flex items-center justify-center gap-2 mt-4">
<Link to={firstRoute}>
<div className="flex items-center justify-around gap-2 bg-white shadow-xl rounded-full py-2 px-3 md:px-8">
<img
src={firstIcon}
alt="Login Icons"
className="w-2/6 md:w-4/5"
/>
<div className="font-bold text-xs md:text-sm uppercase">
{firstOptionLogin}
</div>
</div>
</Link>
<Link to={secondRoute}>
<div className="flex items-center justify-around gap-2 bg-white shadow-xl rounded-full py-2 px-3 md:px-10">
<img
src={secondIcon}
alt="Login Icons"
className="w-2/6 md:w-4/5"
/>
<div className="font-bold text-xs md:text-sm uppercase">
{secondOptionLogin}
</div>
</div>
</Link>
</div>
{/* End of Login Option */}
{/* Alternative Register */}
<div className="flex items-center justify-center gap-2 mt-4 text-xs md:text-sm">
<p>Don't have an account?</p>
<Link
to="/signup"
className="text-[#DE1B1B] font-bold text-xs md:text-sm"
>
Sign Up
</Link>
</div>
{/* End of Alternative Register */}
</div>
</div>
);
}
CASE CLOSED, in the form section onSubmit={handleSubmit} I delete it to just form, then onSubmit={handleSubmit} I move it to button to become onClick={handleSubmit}.
thank you for answering my question. i appreciate it

Add/delete draggable item in beautiful drag and drop (dnd)

First, I'm new to React.
So, I've been making some drag and drop feature while there are also add and delete item feature on it. There are only 2 jsx file that I use, first is DragDropContext and the second is Column (Column with draggable item on it).
Here some code for your better understanding
<DragDropContext onDragEnd={onDragEnd}>
<div className="w-full md:w-[80vw] h-screen p-5 lg:p-20 overflow-y-scroll text-gray-800 bg-slate-100">
<h3 className='text-2xl font-bold'>Favorite Page</h3>
<div className='flex justify-between items-center mt-8'>
<div>
<input type="text" placeholder='type something...' className='p-2 rounded' />
<input type="button" value="Add" className='p-2 rounded bg-indigo-300 ml-4' />
</div>
<div>
<button onClick={onOff}
className={`px-4 py-2 rounded-full text-white ${isToggled ? 'bg-indigo-500': 'bg-slate-400'}`}>{`${isToggled ? 'Edit Page' : 'Save Page'}`}</button>
</div>
</div>
{isToggled ?
<div className='flex mt-5 w-full gap-5 h-fit'>
{state.columnOrder.map((columnId) => {
const column = state.columns[columnId];
const tasks = column.taskIds.map(taskId => state.tasks[taskId]);
// console.log(tasks);
return <Column key={column.id} column={column} tasks={tasks} dataPost={dataPost} enable={true} color={'bg-slate-100'} toggle={isToggled}/>
})}
</div>
:
<div className='flex mt-5 w-full gap-5 h-fit'>
{state.columnOrder.map((columnId) => {
const column = state.columns[columnId];
const tasks = column.taskIds.map(taskId => state.tasks[taskId]);
// console.log(tasks);
return <Column key={column.id} column={column} tasks={tasks} dataPost={dataPost} enable={false} color={'bg-white'} deleteItem={deleteItem}/>
})}
</div>
}
</div>
</DragDropContext>
and this one is for Column
const Column = ( {column, tasks, enable, color, deleteItem, toggle}) => {
return(
<div className={`${column.colorBody} w-full rounded-xl overflow-hidden`}>
<p className={` ${column.colorHead} w-full p-4 text-center text-lg font-light text-white`}>{column.title}</p>
<Droppable droppableId={column.id}>
{(droppableProvided, droppableSnapshot) => (
<div key={column.id} className='w-full h-fit p-5 flex flex-col gap-4' ref={droppableProvided.innerRef} {...droppableProvided.droppableProps}>
{tasks.map((task, index) =>(
<Draggable key={task.id} draggableId={`${task.id}`} index={index} isDragDisabled={enable}>
{(draggableProvided, draggableSnapshot) => (
<div className={`${color} w-full flex justify-between rounded h-fit overflow-hidden ${draggableSnapshot.isDragging? 'border-4 border-indigo-400' : ''}`} id={task.id}
ref={draggableProvided.innerRef}
{...draggableProvided.draggableProps}
{...draggableProvided.dragHandleProps}
>
<div className="flex">
<img className="w-[25%] object-cover" src={`http://127.0.0.1:8000/storage/${task.image}`} alt="" />
<p className='p-4 w-[75%]'>{task.title}</p>
</div>
<button onClick={() => {deleteItem(task.id, column.id)}} className={`button-x ${toggle? 'hidden' : 'block'} h-full bg-red-400 text-white flex items-center justify-center pt-2 pr-2 pb-4 pl-4 rounded-bl-full`}><i className="bi bi-x-lg"></i></button>
</div>
)}
</Draggable>
))}
{droppableProvided.placeholder}
</div>
)}
</Droppable>
</div>
Actually, I'm successful at deleting the item. Still, it throws errors in console and when I drop item on the place that I delete the item before, it'll go to the top left corner and back to the deleted position (place that I drop earlier, like a boomerang). The way I deleted the item is only with deleting the div (draggable item), and when i tried to update the state, it completely not rendering on browser.
The error that throws by console are
Unable to find drag handle with id "1" as no handle with a matching id was found -> in yellow
and
`A setup problem was encountered.
Invariant failed: Draggable[id: 1]: Unable to find drag handle` -> in red
Probably if PublicDraggable key="xx" component is deleted, the error would be gone, but it can't be done that way, right?
So, maybe I need some enlightenment, which function or where is the thing that needs and store Draggable Id except on the div.

Main checkbox selecting all cards when checked

I am building a component where I am grouping cards by regions. I have a checkbox by the region name and when its checked I want to be able to select all the cards in the region.
This is how my cards are displayed by region:
<div className="pl-14 text-black font-nunito mt-8 ml-3 text-2xl">
{_.map(_.keysIn(groups), (region) => {
return (
<>
<div className="flex justify-between">
<div className="flex">
<Checkbox
className="bg-transparent shadow-none text-black hover:bg-transparent"
color="primary"
/>
<p className="mt-1">{_.capitalize(region)}</p>
</div>
<div className="pr-16">
<Button variant="text" className="text-lightBlue">
View More
</Button>
</div>
</div>
<UserCards groupedUser={groups[region]} />
</>
);
})}
</div>
And my cards look like this:
const UserCards = ({ groupedUser }) => {
return groupedUser.map((user) => (
<div className="cardContainer">
<div className="card shadow-customShadow">
<Checkbox
key={user.email}
className="bg-transparent shadow-none text-black mb-14 hover:bg-transparent"
color="primary"
onChange={(event) => {
if (event.target.checked) {
const data = [...userEmails];
data.push(user.email);
setUserEmails(data);
} else {
const data = [...userEmails];
const index = data.indexOf(user.email);
data.splice(index, 1);
setUserEmails(data);
}
}}
checked={_.includes(userEmails, user.email)}
/>
<div>
<div className="mt-2 text-lg">
{information stored here}
</div>
<div className="mt-2 text-lg">
{information stored here}
</div>
</div>
</div>
</div>
));
};
How can I tell the region check box to check all the cards?

yup validation 2 of 3 inputs required

I have yup validation in my form. I want to validate if user compleate minimum 2 of 3 inputs. When user not compleate i want change only a color of text to red. How can i setup my schema to do that. Here's my form:
<form>
{!loading ? (
<Paper title={t('common:cardTitles.extendDevice')} {...register('extendDevice')}>
<div className="flex md:flex-row flex-col justify-center items-center md:justify-between border-b-[1px] md:pb-6 pb-[17px]">
<h3 className="font-bold subheading">{t('common:deviceData')}</h3>
<div className="flex flex-row gap-1">
<ErrorIcon className="text-[#80858F] w-6" />
<p
className={mergeClasses(
'md:text-sm text-xs text-[#80858F]',
errors.extendDevice ? 'text-red-600' : 'text-[#80858F]',
)}
>
{t('common:errors.atLeastTwoFields')}
</p>
</div>
</div>
<div className="md:pt-6 pt-[17px] grid md:grid-cols-2 gap-4">
<TextInput
{...register('serialNumber')}
label={t('common:labels.serialNumber')}
name="serialNumber"
placeholder={t('common:placeholders.typeSerialNumber')}
/>
<TextInput
{...register('businessNumber')}
label={t('common:labels.businessNumber')}
name="business-number"
placeholder={t('common:placeholders.typeBusinessNumber')}
/>
</div>
<div className="pt-4">
<NumberInput
{...register('pinNumber')}
label={t('common:labels.pin')}
name="pin-number"
placeholder={t('common:placeholders.typePinNumber')}
/>
</div>
<div className="flex w-full justify-end pt-4">
<Button
className="py-3.5 px-6 bg-[#336BB3] text-white md:w-[115px] w-full"
label={t('common:labels.verify')}
onClick={handleSubmit(onSubmit)}
type="submit"
/>
</div>
</Paper>
) : (
<VerificationInProgress />
)}
</form>
You can write a test in YUP to check if specific fields have been entered.
const formValidation = Yup.object().shape({
name: Yup.string().test(
"oneOfRequired",
"One of the three fields need to be filled in",
function (item) {
return this.parent.name || this.parent.surname || this.parent.country;
}
),
surname: Yup.string().test(
"oneOfRequired",
"One of the three fields need to be filled in",
function (item) {
return this.parent.name || this.parent.surname || this.parent.country;
}
),
country: Yup.string().test(
"oneOfRequired",
"One of the three fields need to be filled in",
function (item) {
// Check if one of them have been filled in
return this.parent.name || this.parent.surname || this.parent.country;
}
)
});
Here is a codesandbox : https://codesandbox.io/s/goofy-bell-ji28jy?file=/src/App.js:279-302

button only clicks once, at one div element

this is the onclick function
export function changeColorButton() {
document.getElementById("friendDiv").style.background = "grey";
}
this is the output file. I want every button to be clickable and give background grey
{data.projects.map((project, key) => {
return (
<div id="friendDiv" className="relative">
<div key={key} className="flex flex-row items-center space-x-6 mb-6">
<img src={project.image} />
<div>
<h1 key={key} class=" text-xl font-bold">
{project.name}
</h1>
</div>
<button
className="absolute right-10 bg-bgButtonAddPeople p-2"
onClick={changeColorButton}
>
Legg til
</button>
</div>
</div>
);
});
}
You would just need to componentize the div element that is being mapped. So you can follow an approach like this.
Each FriendDiv element would have its own instance of changeColorButton, so it would apply the color to its own element.
FriendDiv.js
const FriendDiv = ({ key, project }) => {
const [isGrey, setIsGrey] = useState(false);
const changeColorButton = () => {
setIsGrey(!isGrey);
};
return (
<div
style={{ backgroundColor: isGrey ? 'grey' : 'default-color}}
id="friendDiv"
className="relative"
>
<div key={key} className="flex flex-row items-center space-x-6 mb-6">
<img src={project.image} />
<div>
<h1 key={key} class=" text-xl font-bold">
{project.name}
</h1>
</div>
<button
className="absolute right-10 bg-bgButtonAddPeople p-2"
onClick={changeColorButton}
>
Legg til
</button>
</div>
</div>
);
};
App.js
const App = () => {
return data.projects.map((project, key) => {
return <FriendDiv project={project} key={key} />;
});
};

Resources