mirror of
https://github.com/nextui-org/nextui.git
synced 2025-12-08 19:26:11 +00:00
* fix(select): `SelectItem` does not accept value props * refactor: do not use the index as `key` * Update .changeset/light-hairs-draw.md * chore: remove unnecessary `value` props * chore: update changeset * refactor: remove unnecessary value prop --------- Co-authored-by: WK Wong <wingkwong.code@gmail.com>
160 lines
4.2 KiB
JavaScript
160 lines
4.2 KiB
JavaScript
import {Form, Input, Select, SelectItem, Checkbox, Button} from "@heroui/react";
|
|
|
|
export default function App() {
|
|
const [password, setPassword] = React.useState("");
|
|
const [submitted, setSubmitted] = React.useState(null);
|
|
const [errors, setErrors] = React.useState({});
|
|
|
|
// Real-time password validation
|
|
const getPasswordError = (value) => {
|
|
if (value.length < 4) {
|
|
return "Password must be 4 characters or more";
|
|
}
|
|
if ((value.match(/[A-Z]/g) || []).length < 1) {
|
|
return "Password needs at least 1 uppercase letter";
|
|
}
|
|
if ((value.match(/[^a-z]/gi) || []).length < 1) {
|
|
return "Password needs at least 1 symbol";
|
|
}
|
|
|
|
return null;
|
|
};
|
|
|
|
const onSubmit = (e) => {
|
|
e.preventDefault();
|
|
const data = Object.fromEntries(new FormData(e.currentTarget));
|
|
|
|
// Custom validation checks
|
|
const newErrors = {};
|
|
|
|
// Password validation
|
|
const passwordError = getPasswordError(data.password);
|
|
|
|
if (passwordError) {
|
|
newErrors.password = passwordError;
|
|
}
|
|
|
|
// Username validation
|
|
if (data.name === "admin") {
|
|
newErrors.name = "Nice try! Choose a different username";
|
|
}
|
|
|
|
if (Object.keys(newErrors).length > 0) {
|
|
setErrors(newErrors);
|
|
|
|
return;
|
|
}
|
|
|
|
if (data.terms !== "true") {
|
|
setErrors({terms: "Please accept the terms"});
|
|
|
|
return;
|
|
}
|
|
|
|
// Clear errors and submit
|
|
setErrors({});
|
|
setSubmitted(data);
|
|
};
|
|
|
|
return (
|
|
<Form
|
|
className="w-full justify-center items-center space-y-4"
|
|
validationErrors={errors}
|
|
onReset={() => setSubmitted(null)}
|
|
onSubmit={onSubmit}
|
|
>
|
|
<div className="flex flex-col gap-4 max-w-md">
|
|
<Input
|
|
isRequired
|
|
errorMessage={({validationDetails}) => {
|
|
if (validationDetails.valueMissing) {
|
|
return "Please enter your name";
|
|
}
|
|
|
|
return errors.name;
|
|
}}
|
|
label="Name"
|
|
labelPlacement="outside"
|
|
name="name"
|
|
placeholder="Enter your name"
|
|
/>
|
|
|
|
<Input
|
|
isRequired
|
|
errorMessage={({validationDetails}) => {
|
|
if (validationDetails.valueMissing) {
|
|
return "Please enter your email";
|
|
}
|
|
if (validationDetails.typeMismatch) {
|
|
return "Please enter a valid email address";
|
|
}
|
|
}}
|
|
label="Email"
|
|
labelPlacement="outside"
|
|
name="email"
|
|
placeholder="Enter your email"
|
|
type="email"
|
|
/>
|
|
|
|
<Input
|
|
isRequired
|
|
errorMessage={getPasswordError(password)}
|
|
isInvalid={getPasswordError(password) !== null}
|
|
label="Password"
|
|
labelPlacement="outside"
|
|
name="password"
|
|
placeholder="Enter your password"
|
|
type="password"
|
|
value={password}
|
|
onValueChange={setPassword}
|
|
/>
|
|
|
|
<Select
|
|
isRequired
|
|
label="Country"
|
|
labelPlacement="outside"
|
|
name="country"
|
|
placeholder="Select country"
|
|
>
|
|
<SelectItem key="ar">Argentina</SelectItem>
|
|
<SelectItem key="us">United States</SelectItem>
|
|
<SelectItem key="ca">Canada</SelectItem>
|
|
<SelectItem key="uk">United Kingdom</SelectItem>
|
|
<SelectItem key="au">Australia</SelectItem>
|
|
</Select>
|
|
|
|
<Checkbox
|
|
isRequired
|
|
classNames={{
|
|
label: "text-small",
|
|
}}
|
|
isInvalid={!!errors.terms}
|
|
name="terms"
|
|
validationBehavior="aria"
|
|
value="true"
|
|
onValueChange={() => setErrors((prev) => ({...prev, terms: undefined}))}
|
|
>
|
|
I agree to the terms and conditions
|
|
</Checkbox>
|
|
|
|
{errors.terms && <span className="text-danger text-small">{errors.terms}</span>}
|
|
|
|
<div className="flex gap-4">
|
|
<Button className="w-full" color="primary" type="submit">
|
|
Submit
|
|
</Button>
|
|
<Button type="reset" variant="bordered">
|
|
Reset
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
|
|
{submitted && (
|
|
<div className="text-small text-default-500 mt-4">
|
|
Submitted data: <pre>{JSON.stringify(submitted, null, 2)}</pre>
|
|
</div>
|
|
)}
|
|
</Form>
|
|
);
|
|
}
|