Skip to content

Instantly share code, notes, and snippets.

@Masheen88
Created October 21, 2024 14:56
Show Gist options
  • Select an option

  • Save Masheen88/0f3a8562a5ee3814d1880da370c35577 to your computer and use it in GitHub Desktop.

Select an option

Save Masheen88/0f3a8562a5ee3814d1880da370c35577 to your computer and use it in GitHub Desktop.
React Form Validation Component
import { useForm, Controller } from "react-hook-form";
import { useEffect } from "react";
// Define validation rules
const validationRules = {
required: {
value: true,
message: "This field is required.",
},
email: {
value: /^[^\s@]+@[^\s@]+\.[^\s@]+$/,
message: "Invalid email format.",
},
phone: {
value: /^\(?\d{3}\)?[-.\s]?\d{3}[-.\s]?\d{4}$/,
message: "Invalid phone number format.",
},
min: (minValue) => ({
value: minValue,
message: `Minimum ${minValue} characters required.`,
}),
};
// Define the custom form component
const CustomInput = ({
name,
type = "text",
placeholder = "",
required = false,
rules = "",
sampleText = "",
options = [],
selectPlaceholder = "Please select an option",
}) => {
const {
control,
register,
formState: { errors },
} = useForm();
// Function to dynamically set rules based on type
const getDefaultRulesForType = (type) => {
switch (type) {
case "email":
return validationRules.email;
case "tel":
return validationRules.phone;
case "text":
return validationRules.min(2);
default:
return {};
}
};
const combinedRules = {
...getDefaultRulesForType(type),
...rules,
...(required && validationRules.required),
};
return (
<div className="mb-4">
{type === "select" ? (
<Controller
name={name}
control={control}
rules={combinedRules}
render={({ field }) => (
<select
{...field}
className="w-full border border-gray-300 dark:border-gray-600 rounded-md px-3 py-2 focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:bg-gray-700 dark:text-gray-300 dark:focus:ring-indigo-300"
>
<option value="" disabled>
{selectPlaceholder}
</option>
{options.map((option, index) => (
<option key={index} value={option.value}>
{option.label}
</option>
))}
</select>
)}
/>
) : (
<input
type={type}
{...register(name, combinedRules)}
placeholder={placeholder}
className="w-full border border-gray-300 dark:border-gray-600 rounded-md px-3 py-2 focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:bg-gray-700 dark:text-gray-300 dark:focus:ring-indigo-300"
/>
)}
{errors[name] && (
<span className="text-red-400 text-sm italic">
{errors[name]?.message}
{sampleText && ` Example: ${sampleText}`}
</span>
)}
</div>
);
};
export default CustomInput;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment