iway1 / react-ts-form Goto Github PK
View Code? Open in Web Editor NEWHome Page: https://react-ts-form.com
License: MIT License
Home Page: https://react-ts-form.com
License: MIT License
Is there any way to access the formState
in a custom form implementation? We want to display some kind of loading spinner when the form is submitting.
When i'm in a field, i can easily use useTsController
but this is only allowed within fields, not in forms.
Is your feature request related to a problem? Please describe.
The concept of this library is very similar to my own implementation.
I've opted for a composition Api rather than prop based.
Would you be interested in discussing it?
Describe the solution you'd like
Composition Api vs prop Api.
1.0.6
No response
Create multiple array schemas with different base types:
const mapping = [
[z.string().array(), StringArrayField],
[z.number().array(), NumberArrayField],
] as const
With the current implementation, they would each map to the StringArrayField which is unexpected.
When checking for equality, the package should consider the arrays inner type.
No response
^1.0.10
No response
const schema = z.object({
url: z.string().describe('URL // https://google.com'),
})
The placeholder should be https://google.com
but it's only https:
. I guess this is because the separator is //
and so the label is segments[0]
and the placeholder segments[1]
.
No response
I have the same issue reported on #50, I'm working with v1.2.0
... I will add a code sandbox that reproduces the error.
Code sandbox that reproduces the error with minimal setup.
https://codesandbox.io/embed/react-ts-form-optional-error-3oz8lk?fontsize=14&hidenavigation=1&theme=dark
Code example, just in case.
const MAX_FILE_SIZE = 1000000000000;
export const FileSchema = createUniqueFieldSchema(
z
.any()
.refine((value) => !!value && !!value.file, "Upload a file is required.")
.refine(
(value) => value?.file?.size <= MAX_FILE_SIZE,
`Max file size is 5MB.`
),
"FileSchema"
);
const FileSchemaComponent = () => <div>{`FileSchema :)`}</div>;
// create the mapping
const mapping = [[FileSchema, FileSchemaComponent]] as const; // ๐ `as const` is necessary
// A typesafe React component
const MyForm = createTsForm(mapping);
// Creates Schema
const schema = z.object({
file: FileSchema.optional() // if .optional is added to a schema it stops working
// My Original file field has a description, just in case I let an example without it, the issue persists in both cases
// fileWithDescript: FileSchema.optional().description('Label // Description') // if .optional is added to a schema it stops working
});
Originally posted by @FedeMadoery in #50 (comment)
Prop types seems to break when optional/nullable/nullish are not in the correct order. See the reprodcution below
TL;DR:
optional().nullable()
worksnullable().optional()
does notnullish()
does not, as it is equivalent to nullable().optional()
import { TextInput } from "@mantine/core";
import { createTsForm, useTsController } from "@ts-react/form";
import { z } from "zod";
const TextField = ({ description }: { description?: string }) => {
const { field, error } = useTsController<string>();
return (
<TextInput
value={field.value}
onChange={(e) => field.onChange(e.target.value)}
label={field.name}
placeholder={description}
error={error?.errorMessage}
/>
);
};
const mapping = [[z.string(), TextField]] as const;
export const Form = createTsForm(mapping);
export const MyFormComponent = () => {
return (
<Form
schema={z.object({
displayNameOptionalNullable: z.string().optional().nullable(),
displayNameNullableOptional: z.string().nullable().optional(),
displayNameNullish: z.string().nullish(),
})}
props={{
displayNameOptionalNullable: {
// Works, no TS errors
description: "",
},
displayNameNullableOptional: {
// Does not work, Type '{ description: string; }' is not assignable to type 'undefined'
description: "",
},
displayNameNullish: {
// Does not work, Type '{ description: string; }' is not assignable to type 'undefined'
description: "",
},
}}
onSubmit={() => {
/* ... */
}}
/>
);
};
Would it be useful to have other callback functions on the form component like onInvalidSubmit
, onDirtyChange
, etc?
Feel free to comment with any callbacks you think might be useful with a description of which callback functions you might want to see added to the form component.
Should throw a type error if your form schema includes a zod type that's not present in the mapping
Complex forms sometimes have some sort of dynamic lists, where the user can add/remove/swap fields to the form.
Is it a goal of react-ts-form to have something handling those?
Library doesn't support .transform
on schemas currently:
const mapping = [[z.string(), TextField]] as const;
const Form = createTsForm(mapping);
const FormSchema = z.object({textField: z.string().tranform(v=>parseInt(v));
<Form schema={FormSchema} /> // Errors no found schema
Would be nice to be able to transform / preprocess stuff in the schema and still have it match the schema.
Couldn't find anything about dealing with arrays in the docs. I guess there needs to be native useFieldArray
support?
1.1.2
No response
Do #43
Should render matching mapping element
No response
From the limitations section:
@ts-react/form allows you to pass props to your components and render elements in between your components, which is good for almost all form designs out there. Some designs may not be easily achievable. For example, if you need a container around multiple sections of your form, this library doesn't allow splitting child components into containers at the moment. (Though if it's a common-enough use case and you'd like to see it added, open an issue!)
Not sure what will be the right approach but I like to be declarative as possible
For now, I experimented with this approach, not sure I like the DX, too much magic?
Passing some components to beforeElement, like section header GridColumnHeader
before layout the childrens, do some Children.toArray(children) tricks to split them based on the beforeElement and plot each part as separate section
Not sure I like this approach but it seem to do the work
I noticed you deprecated enum support with the reasoning the strings() can do everything enums can. The problem I'm finding is that the values I get back from the form on submit have strings in their type instead of enums (as you'd expect). I'm using your workaround to pass select options to the component but what's the workaround to get the types to be correct?
Our GQL input mutations have actual enums so i'd love to be able to define a typed form that matches that type exactly. Is there an alternative solution I just haven't found?
I'm wondering if it would be possible to lower the support versions of React in the peerDependencies. I would love to use the library, but my team is currently forced to use React 17, so installing requires us to use overrides
in each project we want to add it to. It would be nice not to have to do this if possible.
If there's no concerns, I'm happy to open a PR to change this to match the range currently supported by react-hook-form
("^16.8.0 || ^17 || ^18"
) https://github.com/react-hook-form/react-hook-form/blob/master/package.json#L122
// components/form.ts
import { createTsForm, createUniqueFieldSchema } from '@ts-react/form'
import { z } from 'zod'
import { NumberField } from './NumberField'
import { TextField } from './TextField'
export const StringSchema = createUniqueFieldSchema(z.string(), 'string')
export const NumberSchema = createUniqueFieldSchema(z.number(), 'number')
const mapping = [
[StringSchema, TextField],
[NumberSchema, NumberField],
] as const
export const Form = createTsForm(mapping)
// pages/index.tsx
import { z } from 'zod'
import { Form, NumberSchema, StringSchema } from '../components/form'
const schema = z.object({
name: StringSchema.optional(), // if .optional is added to a schema it stops working
age: NumberSchema,
})
export function Home() {
return (
<Form
schema={schema}
onSubmit={(v) => {
console.log(v)
}}
formProps={{
className: 'flex flex-col gap-4 px-4 max-w-5xl lg:grid lg:grid-cols-2',
}}
/>
)
}
1.0.9
No response
Copy the code and run it on nextjs application
I am not sure if this is the expected behaviour for createUniqueFieldSchema but this code generates the error: Duplicate id passed to createFieldSchema: SelectMenu101
import { z } from "zod";
import { TextArea } from "./TextArea";
import { createTsForm, createUniqueFieldSchema } from "@ts-react/form";
import { DashboardLayout } from "./DashboardLayout";
import { SelectMenu } from "./SelectMenu";
const SelectMenuFieldSchema = createUniqueFieldSchema(
z.string(),
"SelectMenu101"
);
const mapping = [
[z.string(), TextArea],
[SelectMenuFieldSchema, SelectMenu],
] as const;
const GeneratorForm = createTsForm(mapping);
const ProposalSchema = z.object({
credits: SelectMenuFieldSchema,
product: z.string(),
profession: z.string(),
});
export default function MyForm() {
function onSubmit(data: z.infer<typeof ProposalSchema>) {
console.log(data);
}
return (
<DashboardLayout>
<main className="p-4">
<GeneratorForm
schema={ProposalSchema}
onSubmit={onSubmit}
renderAfter={() => (
<div className="pt-5">
<div className="flex justify-end">
<button
type="button"
className="rounded-md border border-gray-300 bg-white py-2 px-4 text-sm font-medium text-gray-700 shadow-sm hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2"
>
Cancel
</button>
<button
type="submit"
className="ml-3 inline-flex justify-center rounded-md border border-transparent bg-indigo-600 py-2 px-4 text-sm font-medium text-white shadow-sm hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2"
>
Generate
</button>
</div>
</div>
)}
props={{
credits: {
label: "Available credits",
options: ["5 credit", "1 credit", "10 credits"],
defaultValue: "5 credit",
},
product: {
label: "Whats your product or solution service about ? required",
placeholder: "Product or solution service",
helpText:
"Write a few words about the product or service you are building.",
},
profession: {
label: "What does your potential client do ? Profession required",
placeholder: "Profession",
helpText:
"Write a few words about the profession of your potential customers.",
},
}}
/>
</main>
</DashboardLayout>
);
}
Server Error
Error: Duplicate id passed to createFieldSchema: SelectMenu101. Ensure that each id is only being used once and that createFieldSchema is only called at the top level.
I created custom component that looks like this:
import { createTsForm } from "@ts-react/form"
import { TextField } from "./TextField"
import { z } from "zod"
interface Props {
children: JSX.Element
onSubmit: () => void
}
// const FindOrderSchema = z.object({
// email: z.string().email("Enter a real email please."),
// orderNumber: z.string(),
// })
function Form({ children, onSubmit }: Props) {
return (
<form onSubmit={onSubmit}>
{children}
<button type="submit">submit</button>
</form>
)
}
const mapping = [[z.string(), TextField]] as const
export const FindOrderForm = createTsForm(mapping, { FormComponent: Form })
Read https://github.com/iway1/react-ts-form#customizing-form-components
However I am confused, where does schema go in this case?
I cannot do this:
1.0.10
function Select({ options }: { options: string[] }) {
// ...
}
export const SelectStringSchema = createUniqueFieldSchema(z.string(), "select");
const mapping = [
[z.string(), TextInput],
[z.number(), NumberInput],
[z.boolean(), Checkbox],
[SelectStringSchema, Select] as const,
] as const;
In this very simple example, we the Form component doesn't expect the options
props from Select - there's no error when we don't pass it and we get an error if we do try to pass it.
If we could pass hidden values as a prop to the form component, it would make it viable to share most if not all form schemas with trpc-like backends which could make synchronization between front end and backend very easy in cases where the backend is using zod schemas for input.
For example, imagine we had a "comment" form that created a comment for a post. The form only needs to include a text field in the UI, but the backend expects both the text of the comment and the ID of the post:
export const MyCommentSchema = z.object({
text: z.string(),
postId: z.string(),
})
import { MyCommentSchema } from 'schema'; // import schema from shared package / file
// trpc router
const trpcRouter = t.router({
postComment: z.procedure.input(MyCommentSchema).mutation(/* do stuff */)
})
In our next.js page for example:
import { MyCommentSchema } from 'schema'; // import schema from shared package / file
// front end
const MyPage = ()=>{
const mutation = api.postComment.useMutation()
const {query: {postId}} = useRouter()
return (
<Form
schema={MyCommentSchema}
onSubmit={mutation.mutate}
hiddenValues={{
postId: postId,
}}
/>
)
}
No component would be rendered for the postId
field (since we don't want users to have to input hidden values), and the hidden value would get passed to the onSubmit
callback.
Any additional changes to our shared schema would both add the field to the input of the trpc router, and also render a new field on the frontend. Enables fullstack typesafe form submission with a single source of truth.
import { useTsController } from '@ts-react/form'
export function NumberField({ req }: { req: number }) {
const {
field: { onChange, value },
error,
} = useTsController<number>()
console.log('value: ', value) // if default value is 1 it still logs 'value: 1' even when trying to erase the value
return (
<>
<span>
<span>{`req is ${req}`}</span>
<input
type="number"
value={value !== undefined ? value + '' : ''}
onChange={(e) => {
const value = parseInt(e.target.value)
if (isNaN(value)) onChange(undefined)
else onChange(value)
}}
/>
{error && error.errorMessage}
</span>
</>
)
}
Is your feature request related to a problem? Please describe.
We are testing our react app and that requires the input
element to have a certain id
prop like emailAddress
or orderNumber
.
I read docs and could not find a way to add them using this library as you seem to only be able to pass props or id to the wrapper div that wraps over the inputs and not each individual input itself. Unless I am mistaken.
Describe the solution you'd like
Be able to add id
prop to each individual input box.
My TextField looks like this:
interface Props {
placeholder: string
}
export function TextField({ placeholder }: Props) {
const { field, error } = useTsController<string>()
console.log(placeholder)
return (
<>
<StyledInput
value={field.value ? field.value : ""}
onChange={(e) => {
field.onChange(e.target.value)
}}
/>
{error?.errorMessage && <span>{error?.errorMessage}</span>}
</>
)
}
const StyledInput = styled("input")`
padding: 1rem;
border-radius: 3.125rem;
border: 1px solid rgba(185, 185, 185, 1);
font-size: 1rem;
box-sizing: border-box;
font-weight: 500;
::placeholder,
::-webkit-input-placeholder {
color: red;
}
`
Essentially I want to be able to pass placeholder
prop to it but I don't know how.
Because now my Field component is gotten like this:
const mapping = [[z.string(), TextField]] as const
const MyForm = createTsForm(mapping)
And in render I can't do this:
<MyForm
placeholder={"Enter your email and order number"}
schema={FindOrderSchema}
onSubmit={onSubmit}
renderAfter={() => <button type="submit">Submit</button>}
/>
```
I have an address field setup as a complex field. Within that field I have two select fields. 1 for the state/region and the other for the country code.
The issue I'm having is I cannot figure out how to pass options down to these fields. Not sure how to get the code below to appear right. md is not behaving with me today. Any idea how to pass the options down to each select field within the address schema?
this is my form.tsx
`
const mapping = [
[z.string(), TextInput],
[z.boolean(), Checkbox],
[z.number(), NumberInput],
[PasswordSchema, PasswordField] as const,
[PasswordWConfirmSchema, PasswordWConfirmInput] as const,
[AddressSchema, AddressInput] as const,
[SelectSchema, SelectField]
] as const;
const MyForm = createTsForm(mapping);
const SignUpSchema = z.object({
firstName: z.string().describe("First Name"),
lastName: z.string().describe("Last Name"),
email: z.string().email("Enter a real email please.").describe("Email"), // renders TextField
password: PasswordWConfirmSchema,
address: AddressSchema,
})
export function Form() {
function onSubmit(data: z.infer<typeof SignUpSchema>) {
// gets typesafe data when form is submitted
alert(JSON.stringify(data));
}
return (
<MyForm
schema={SignUpSchema}
onSubmit={onSubmit}
renderAfter={() => <button type="submit">Submit</button>}
props={{
address: {
}
}}
/>
);
}
`
My AddressInput.tsx
`
const AddressInput = () => {
const {
field: { value, onChange },
error,
} = useTsController<z.infer>();
const line1 = value?.line1;
const line2 = value?.line2;
const locale = value?.locale;
const region = value?.region;
const postalCode = value?.postalCode;
const countryCode = value?.countryCode;
return (
<label
style={{
fontSize: 16,
display: "flex",
gap: ".5rem",
marginBottom: ".5rem",
justifyContent: "flex-end",
}}
>
City
<input
style={{ padding: "0.25rem" }}
type="text"
value={locale}
onChange={(e) => onChange({ ...value, locale: e.target.value })}
/>
</label>
{error?.locale && <div style={{ color: "red" }}>{error.locale.errorMessage}</div>}
<div style={{
display: "flex",
gap: ".5em",
}}>
<div style={{ maxWidth: "30%" }}>
</div>
<div style={{ maxWidth: "70%" }}>
<label
style={{
fontSize: 16,
display: "flex",
gap: ".5em",
marginBottom: ".5rem",
justifyContent: "flex-end",
}}
>
Zip Code
<input
style={{ padding: "0.25rem", maxWidth: "50%", }}
type="text"
value={postalCode}
onChange={(e) => onChange({ ...value, postalCode: e.target.value })}
/>
</label>
{error?.postalCode && <div style={{ color: "red" }}>{error.postalCode.errorMessage}</div>}
</div>
</div>
</div>
)
}
export default AddressInput
const zipcodeRegex = RegExp('^\d{ 5} -\d{ 4} |\d{ 5} | [A - Z]\d[A - Z]\d[A - Z]\d$')
export const AddressSchema = createUniqueFieldSchema(z.object({
line1: z.string().describe("Street Address"),
line2: z.string().optional(),
locale: z.string().describe("City"),
region: SelectSchema.describe("State"),
postalCode: z.string().regex(zipcodeRegex, "Please Enter a valid Zip Code.").describe("Zip Code"),
countryCode: SelectSchema.describe("Country Code"),
}), "address")
Select
function SelectField({ options }: { options: string[] }) {
const { field, error } = useTsController();
const label = useDescription();
return (
<>
<label
style={{
fontSize: 16,
display: "flex",
gap: ".5rem",
marginBottom: ".5rem",
justifyContent: "flex-end",
}}
>
{label.label}
<select
value={field.value ? field.value : "none"}
onChange={(e) => {
field.onChange(e.target.value);
}}
>
{!field.value && <option value="none">Please select...</option>}
{options.map((e) => (
<option key={e} value={e}>
{e}
</option>
))}
</select>
</label>
<span>{error?.errorMessage && error.errorMessage}</span>
</>
);
}
export default SelectField
export const SelectSchema = createUniqueFieldSchema(z.string(), "DropdownSelect")`
Is your feature request related to a problem? Please describe.
I'm always frustrated when can't see link to playground example to quickly open and try
Describe the solution you'd like
Add playground examples to codesandbox/stackblitz
Right now it isn't possible to have a unique enum field that works in any useful way.
I think the only way to implement this would be creating a new function specifically for creating unique enum fields, something like:
const RadioSchema = createUniqueEnumField('id');
const MyForm = z.object({
radio: MyUniqueEnum.enum(["one", "two"])
})
Needs to be able to pass in options at the form level and only be passed to the mapping once per field component type.
Hello, amazing lib. I see the field to improve it.
Currently, we have something like this:
const Colors = ["red", "green", "blue"] as const;
const FavoriteColor = z.enum(Colors).array(); //
// const FavoriteColor = z.array().enum(Colors)
const mapping = [
[FavoriteColor, MultiCheckbox],
] as const;
const Schema = z.object({
favoriteColor: FavoriteColor.describe("Favorite Color"),
});
const MultiCheckbox = (props: { options: string[] }) => {
const { options } = props;
...
}
Const App = ()=>
<MyForm
form={form}
schema={Schema}
props={{
favoriteColor: {
options: FavoriteColor._def.type.options,
},
}}
/>
It works, but I want it to look like this!
const Colors = ["red", "green", "blue"] as const;
const FavoriteColor = z.enum(Colors).array(); //
// const FavoriteColor = z.array().enum(Colors)
const mapping = [
[FavoriteColor, MultiCheckbox],
] as const;
const Schema = z.object({
favoriteColor: FavoriteColor.describe("Favorite Color"),
});
const MultiCheckbox = () => {
const options = useEnumValues();
...
}
Const App = ()=>
<MyForm
form={form}
schema={Schema}
/>
I added PR with a proposition for it.
Functionality + tests.
1.6.3
No response
No npm Errors.
npm ERR! code ERESOLVE
npm ERR! ERESOLVE unable to resolve dependency tree
npm ERR!
npm ERR! While resolving: [email protected]
npm ERR! Found: @hookform/[email protected]
npm ERR! node_modules/@hookform/resolvers
npm ERR! @hookform/resolvers@"^3.1.0" from the root project
npm ERR!
npm ERR! Could not resolve dependency:
npm ERR! peer @hookform/resolvers@"^2.8.0" from @ts-react/[email protected]
npm ERR! node_modules/@ts-react/form
npm ERR! @ts-react/form@"^1.6.3" from the root project
npm ERR!
npm ERR! Fix the upstream dependency conflict, or retry
npm ERR! this command with --force, or --legacy-peer-deps
npm ERR! to accept an incorrect (and potentially broken) dependency resolution.
npm ERR!
I read through readme and still confused about it.
1.1.3
https://codesandbox.io/s/react-typescript-forked-j8cy2u?file=/src/App.tsx
Shows *Required
error.
No response
In some forms
, field props are dependen on values from other fields.
How are we going to solve this?
this could be quiet tricky
A solution for now is creating a custom component, which is dependent and loading the formState from the context (when implemented).
This should be documented. :D
Looks like the zodResolver just validates the form but doesn't pass the result of a zod parse on the data to onSubmit. Would be nice to actually parse before submitting to strip out extra fields that may have come along with say a GQL query that aren't updateble: ala https://github.com/colinhacks/zod#strip
1.4.5
https://codesandbox.io/s/cocky-driscoll-0bpr67?file=/src/App.tsx
Number fields should keep getting updated beyond the first call to reset.
No response
Is your feature request related to a problem? Please describe.
I want to use asynchronous functions to validate my schemas (using .superRefine
). Specifically, I want to check my backend to make sure that the username and email aren't already in use, like so:
const CreateUserSchema = z
.object({
username: z.string().describe("Username // username"), // renders TextField
email: z
.string()
.email("Enter a real email please.")
.describe("Email // [email protected]")
.optional(), // renders TextField
name: z.string().describe("Name // John Doe").optional(),
})
.superRefine(async (values, ctx) => {
const zodEmail = z.string().email().safeParse(values.email);
const [userByUsername, userByEmail] = await getUsernameAndEmail(values.username, zodEmail.data);
if (userByUsername.user !== null) {
ctx.addIssue({
code: "custom",
message: "Username already taken.",
path: ["username"],
});
}
if (userByEmail.user !== null) {
ctx.addIssue({
code: "custom",
message: "Email already taken.",
path: ["email"],
});
}
});
Technically this works, but I have to adjust my .eslint.json
to include "@typescript-eslint/no-misused-promises": "warn"
, which is undesirable.
Describe the solution you'd like
Initially I thought this was a bug in Zod. I opened an issue, and got a response that I might need to be using parseAsync. I think switching to that might be the solution (although I am admittedly not super familiar with the react-ts-form
source code, so take that with a grain of salt).
Describe alternatives you've considered
For now, I'm just leaving my "@typescript-eslint/no-misused-promises": "warn"
as is. Not ideal, but not progress-stopping either.
Additional context
Add any other context or screenshots about the feature request here.
^1.0.6
Have repo here: https://github.com/nikitavoloboev/test/tree/main/next-13
Can run pnpm i
and pnpm run dev
.
Actual code with inputs here: https://github.com/nikitavoloboev/test/blob/main/next-13/pages/index.tsx
I am not sure what I am doing wrong but every time I try to write in the input boxes I get this error:
I expanded on code that is in readme, perhaps I missed something? Repo was started from latest Next 13 starter.
Thank you.
No warning in console.
A component is changing an uncontrolled input to be controlled. This is likely caused by the value changing from undefined to a defined value, which should not happen. Decide between using a controlled or uncontrolled input element for the lifetime of the component.
My code:
import Card from "../../components/Card"
import Container from "../../components/Container"
import { z } from "zod"
import { TextField } from "../../components/TextField"
import { createTsForm } from "@ts-react/form"
const mapping = [[z.string(), TextField]] as const
const MyForm = createTsForm(mapping)
export default function SearchPage() {
const FindOrderSchema = z.object({
email: z.string().email("Enter a real email please."),
orderNumber: z.string(),
})
function onSubmit(data: z.infer<typeof FindOrderSchema>) {
// gets typesafe data when form is submitted
}
return (
<>
<Container>
<Card
title="Exchange or return your order"
subtitle="Enter your details to find your order"
>
<MyForm
schema={FindOrderSchema}
onSubmit={onSubmit}
renderAfter={() => <button type="submit">Submit</button>}
/>
</Card>
</Container>
</>
)
}
Getting this error though trying to open the page.
Not sure why. My TextField import looks like this:
import { useTsController } from "@ts-react/form"
export function TextField() {
const { field, error } = useTsController<string>()
return (
<>
<input
value={field.value}
onChange={(e) => {
field.onChange(e.target.value)
}}
/>
{error?.errorMessage && <span>{error?.errorMessage}</span>}
</>
)
}
let's say i have a checkbox field - billing address is different from shipping address. I want to show additional fields when this checkbox is ticked (with their own set of validations), and hide these fields when the checkbox is not selected.
Would be great to have an example implementation of every common type of field to get people started:
[x] text
[x] number
[x] dropdown select
[x] multi checkbox
[x] checkbox
Feel free to comment with any other examples that you would want to see in the field examples
v.1.4.2
https://codesandbox.io/s/black-mountain-14xil1?file=/src/App.tsx
Default values passed into the form should appear even when form state is accessed.
No response
I'm trying to use form.watch()
to subscribe to a value in the schema and log it to the console. But the value is not being logged.
Am I doing something wrong here?
Codesandbox:
https://codesandbox.io/s/beautiful-monad-f0cuj0?file=/src/App.tsx
Please tell me if I've missed this but. I think it would be really great to be able to represent a nested schema and have zod automatically walk the objects and render any primitive types if i don't have an z.object() mapping setup.
z.object({
nested : z.object({
numField : z.number()
})
})
would just render whatever is mapped to the number editor and supply default values from the object path and recreate the object on edit automatically so values would be {nested : {numField : 9}}
P.S. We are considering using this very heavily and i'd be happy to contribute if you're open to some of these ideas. (I wrote a custom form gen library at my last job, so I think i have some relevant background that could be useful)
Is your feature request related to a problem? Please describe.
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
Describe the solution you'd like
A clear and concise description of what you want to happen.
Describe alternatives you've considered
A clear and concise description of any alternative solutions or features you've considered.
Additional context
Add any other context or screenshots about the feature request here.
vitest > jest
Although array equality now works, right now we can only support a single set, record, etc without the mapping breaking. Will want to add support for checking the inner types of sets, records, maps as well
My use case is to show an asterisk next to required fields in say my TextField component. I'd like to be able to introspect the schema to see if it is optional / nullable or not. (Maybe there's a better answer than that. If so, would love to hear it)
I need to read useTsController().formState.isSubmitting
from input components, but it just flashes from true to false real quick.
Shouldn't we await here?
react-ts-form/src/createSchemaForm.tsx
Line 381 in 3fcd707
Hello. Sorry if this is specified on the docs or other issue, I wasn't able to find it by looking for 'submitter' or 'submit', etc. Is there a way to access the submitter element from the onSubmit function?. For example:
In the case of having multiple submit buttons for different actions with the same form state:
return (
...
<ul className="dropdown-menu dropdown-menu-dark bg-dark border-primary">
{
['save', 'save as'].map((name) => (
<li key={name}>
<button
type="submit"
name={name}
value={name}
className="dropdown-item dropdown-item-dark"
>{name}</button>
</li>
)
)
}
</ul>
...
)
The current way to get the event data is to store outside of the form component
export function FormContainer({
id,
onSubmit,
children,
header,
}: {
id: string;
onSubmit: () => void;
children: ReactNode;
header: string;
}) {
const { action } = useAction();
const handleSubmit = (event: React.FormEvent<HTMLFormElement>) => {
event.preventDefault();
action.name = ((event.nativeEvent as SubmitEvent).submitter as HTMLInputElement).name;
onSubmit();
}
...
And then the parent component can use the submitter value:
...
const { action } = useAction();
const submitPreset = (data: z.infer<typeof forms.preset>) => {
console.log(action);
console.log(data);
};
...
It doesn't seem ideal, is the event available to the Form's parent element via any callback or form state? Can I modify the callback to include it? How could someone go about supporting multiple submit options? Haven't been able to find info. about it in the docs.
Thank you, very good library :)
I read through readme and I have the error showing if it happens but I would like for it to disappear after 3 seconds.
Is there something I can do to make this easy without creating my own internal setTimeout?
1.1.3
https://codesandbox.io/s/sad-parm-v0m5ig
There is an error if .refine is provided to boolean, if u delete line with refine other boolean works fine.
If u provide boolean with refine to mapping then it seems to work
It should work whether or not refine is specified
No response
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.