Skip to content

Commit

Permalink
Support dynamic config
Browse files Browse the repository at this point in the history
bloodyowl committed Jul 9, 2024
1 parent 3c40da7 commit abb042a
Showing 5 changed files with 150 additions and 7 deletions.
14 changes: 11 additions & 3 deletions src/useForm.ts
Original file line number Diff line number Diff line change
@@ -233,7 +233,11 @@ export const useForm = <Values extends Required<Values>, ErrorMessage = string>(
names.forEach((name) => fields.current[name].callbacks.add(callback));

return () => {
names.forEach((name) => fields.current[name].callbacks.delete(callback));
names.forEach((name) => {
if (fields.current[name] != null) {
fields.current[name].callbacks.delete(callback);
}
});
};
};

@@ -399,7 +403,9 @@ export const useForm = <Values extends Required<Values>, ErrorMessage = string>(
fields.current[name].callbacks.add(callback);

return () => {
fields.current[name].callbacks.delete(callback);
if (fields.current[name] != null) {
fields.current[name].callbacks.delete(callback);
}
};
},
}),
@@ -423,7 +429,9 @@ export const useForm = <Values extends Required<Values>, ErrorMessage = string>(

return () => {
if (isFirstMounting) {
fields.current[name].mounted = false;
if (fields.current[name] != null) {
fields.current[name].mounted = false;
}
}
};
}, [name]);
3 changes: 3 additions & 0 deletions website/src/App.tsx
Original file line number Diff line number Diff line change
@@ -11,6 +11,7 @@ import { AsyncSubmissionForm } from "./forms/AsyncSubmissionForm";
import { BasicForm } from "./forms/BasicForm";
import { CheckboxesForm } from "./forms/CheckboxesForm";
import { CreditCardForm } from "./forms/CreditCardForm";
import { Dynamic } from "./forms/Dynamic";
import { FieldsListenerForm } from "./forms/FieldsListenerForm";
import { IBANForm } from "./forms/IBANForm";
import { InputMaskingForm } from "./forms/InputMaskingForm";
@@ -76,6 +77,7 @@ export const App = () => {
<Link to={Router.IBAN()}>IBAN</Link>
<Link to={Router.CreditCard()}>Credit card</Link>
<Link to={Router.InputMasking()}>Input masking</Link>
<Link to={Router.Dynamic()}>Dynamic fields</Link>
</VStack>
</Flex>
)}
@@ -89,6 +91,7 @@ export const App = () => {
.with({ name: "IBAN" }, () => <IBANForm />)
.with({ name: "CreditCard" }, () => <CreditCardForm />)
.with({ name: "InputMasking" }, () => <InputMaskingForm />)
.with({ name: "Dynamic" }, () => <Dynamic />)
.with(P.nullish, () => <Page title="Not found" />)
.exhaustive()}
</Flex>
131 changes: 131 additions & 0 deletions website/src/forms/Dynamic.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
import { Button } from "@chakra-ui/button";
import { HStack, Spacer } from "@chakra-ui/layout";
import { useToast } from "@chakra-ui/toast";
import { useForm } from "@swan-io/use-form";
import * as React from "react";
import { Input } from "../components/Input";
import { Page } from "../components/Page";

export const Dynamic = () => {
const [fields, setFields] = React.useState<{ key: string; name: string }[]>([]);

const config = React.useMemo(
() =>
Object.fromEntries(
fields.map((item) => [
item.key,
{
strategy: "onBlur" as const,
initialValue: "",
sanitize: (value: string) => value.trim(),
validate: (value: string) => {
if (value === "") {
return "First name is required";
}
},
},
]),
),
[fields],
);

const { Field, resetForm, submitForm } = useForm(config);

const toast = useToast();

const onSubmit = (event: React.FormEvent) => {
event.preventDefault();

submitForm({
onSuccess: (values) => {
console.log("values", values);

toast({
title: "Submission succeeded",
status: "success",
duration: 5000,
isClosable: true,
});
},
onFailure: (errors) => {
console.log("errors", errors);

toast({
title: "Submission failed",
status: "error",
duration: 5000,
isClosable: true,
});
},
});
};

return (
<Page
title="Basic"
description={
<>
A common form example which play with at least two different strategies.
<br />
Note that all values are sanitized using trimming.
</>
}
>
<HStack justifyContent="flex-start" spacing={3}>
<Button
width={100}
onClick={() =>
setFields((fields) => [
...fields,
{ key: crypto.randomUUID(), name: `Field ${fields.length}` },
])
}
>
Add field
</Button>
<Button width={140} onClick={() => setFields((fields) => fields.slice(0, -1))}>
Remove field
</Button>
</HStack>

<Spacer height={8} />

<form
onSubmit={onSubmit}
onReset={() => {
resetForm();
}}
>
{fields.map((field) => (
<Field name={field.key} key={field.key}>
{({ error, onBlur, onChange, ref, valid, value }) => (
<Input
label={field.name}
validation="Required"
strategy="onBlur"
error={error}
onBlur={onBlur}
onChangeText={onChange}
ref={ref}
valid={valid}
value={value}
/>
)}
</Field>
))}

<Spacer height={4} />

<HStack justifyContent="flex-end" spacing={3}>
<Button type="reset" width={100}>
Reset
</Button>

<Button colorScheme="green" type="submit" width={100}>
Submit
</Button>
</HStack>
</form>
</Page>
);
};
1 change: 1 addition & 0 deletions website/src/utils/router.ts
Original file line number Diff line number Diff line change
@@ -10,6 +10,7 @@ const routesObject = {
IBAN: "/iban",
CreditCard: "/credit-card",
InputMasking: "/input-masking",
Dynamic: "/dynamic",
} as const;

export const routes = Dict.keys(routesObject);
8 changes: 4 additions & 4 deletions website/yarn.lock
Original file line number Diff line number Diff line change
@@ -1168,10 +1168,10 @@
resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.14.0.tgz#0bb7ac3cd1c3292db1f39afdabfd03ccea3a3d34"
integrity sha512-aGg7iToJjdklmxlUlJh/PaPNa4PmqHfyRMLunbL3eaMO0gp656+q1zOKkpJ/CVe9CryJv6tAN1HDoR8cNGzkag==

"@swan-io/boxed@^2.1.1":
version "2.1.1"
resolved "https://registry.yarnpkg.com/@swan-io/boxed/-/boxed-2.1.1.tgz#bdf17d725270c8560d2371972427b6f7e80da5d8"
integrity sha512-NzmIVAnJuzuPwm8ZR4I9tUpuo9qjtVNA7aTSZYdSvcJ+y7NTyt9+tCi4y87T3m8hACN2ATMqvTmRtHOSDIIz7w==
"@swan-io/boxed@^2.3.0":
version "2.3.0"
resolved "https://registry.yarnpkg.com/@swan-io/boxed/-/boxed-2.3.0.tgz#aafa19432a3fa2c00d472be7832632619c4ed5ff"
integrity sha512-ubonCw2GLblwsA9rodcDnhLvCY+0d9g0KyMFyzKZa+vPumWQ8IZ6HFjdQT3Nm5yC+/RnSmJ20RMPwOn/06M8Vw==

"@swan-io/chicane@^2.0.0":
version "2.0.0"

0 comments on commit abb042a

Please sign in to comment.