Skip to content

Commit 0ccca22

Browse files
committed
Add support for formprops
1 parent 2ce46ce commit 0ccca22

File tree

13 files changed

+249
-36
lines changed

13 files changed

+249
-36
lines changed

apps/docs/pages/docs/react/api.mdx

+4
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,7 @@ Additional, custom form components can be passed to the `formComponents` prop. T
3535
## uiComponents: Partial\<AutoFormUIComponents>
3636

3737
Override the default UI components with custom components. This allows you to customize the look and feel of the form.
38+
39+
## formProps?: React.ComponentProps\<'form'>
40+
41+
The `formProps` prop allows you to pass additional props directly to the underlying form element. This can be useful for adding custom attributes, event handlers, or other properties to the form.

apps/docs/pages/docs/react/customization.md

+21
Original file line numberDiff line numberDiff line change
@@ -199,3 +199,24 @@ You can also override the default UI components with custom components. This all
199199
}}
200200
/>
201201
```
202+
203+
## Form element customization
204+
205+
In addition to overriding UI components, you can also customize the form element itself using the `formProps` prop:
206+
207+
```tsx
208+
<AutoForm
209+
schema={schemaProvider}
210+
onSubmit={handleSubmit}
211+
formProps={{
212+
className: "my-custom-form",
213+
"data-testid": "user-form",
214+
noValidate: true,
215+
onTouchStart: (e) => {
216+
console.log("onTouchStart", e);
217+
},
218+
}}
219+
/>
220+
```
221+
222+
This allows you to add custom classes, data attributes, or other properties directly to the form element.

apps/docs/pages/docs/react/getting-started.mdx

+19
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,25 @@ const [values, setValues] = useState({});
122122

123123
This allows you to access form methods and state from the parent component. You can use the `onFormInit` prop independent of controlled forms to access the form instance.
124124

125+
## Passing props to the form element
126+
127+
You can pass additional props to the underlying form element using the `formProps` prop:
128+
129+
```tsx
130+
<AutoForm
131+
schema={schemaProvider}
132+
onSubmit={handleSubmit}
133+
formProps={{
134+
className: "my-custom-form-class",
135+
onKeyDown: (e) => {
136+
if (e.key === "Enter") e.preventDefault();
137+
},
138+
}}
139+
/>
140+
```
141+
142+
This allows you to customize the form element's attributes and behavior as needed.
143+
125144
## Submitting the form
126145

127146
You can use the `withSubmit` prop to automatically add a submit button to the form.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import React from "react";
2+
import { AutoForm } from "@autoform/mantine";
3+
import { ZodProvider } from "@autoform/zod";
4+
import { z } from "zod";
5+
import { TestWrapper } from "./utils";
6+
7+
describe("AutoForm Form Props Tests (Mantine)", () => {
8+
const schema = z.object({
9+
name: z.string(),
10+
});
11+
12+
const schemaProvider = new ZodProvider(schema);
13+
14+
it("applies custom form props", () => {
15+
cy.mount(
16+
<TestWrapper>
17+
<AutoForm
18+
schema={schemaProvider}
19+
onSubmit={cy.stub().as("onSubmit")}
20+
withSubmit
21+
formProps={{
22+
className: "custom-form-class",
23+
"data-testid": "custom-form",
24+
onKeyDown: cy.stub().as("onKeyDown"),
25+
}}
26+
/>
27+
</TestWrapper>
28+
);
29+
30+
cy.get("form")
31+
.should("have.class", "custom-form-class")
32+
.and("have.attr", "data-testid", "custom-form");
33+
34+
cy.get('input[name="name"]').type("{enter}");
35+
cy.get("@onKeyDown").should("have.been.called");
36+
});
37+
38+
it("prevents form submission on enter key", () => {
39+
cy.mount(
40+
<TestWrapper>
41+
<AutoForm
42+
schema={schemaProvider}
43+
onSubmit={cy.stub().as("onSubmit")}
44+
withSubmit
45+
formProps={{
46+
onKeyDown: (e) => {
47+
if (e.key === "Enter") e.preventDefault();
48+
},
49+
}}
50+
/>
51+
</TestWrapper>
52+
);
53+
54+
cy.get('input[name="name"]').type("John Doe{enter}");
55+
cy.get("@onSubmit").should("not.have.been.called");
56+
});
57+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import React from "react";
2+
import { AutoForm } from "@autoform/mui";
3+
import { ZodProvider } from "@autoform/zod";
4+
import { z } from "zod";
5+
6+
describe("AutoForm Form Props Tests (MUI)", () => {
7+
const schema = z.object({
8+
name: z.string(),
9+
});
10+
11+
const schemaProvider = new ZodProvider(schema);
12+
13+
it("applies custom form props", () => {
14+
cy.mount(
15+
<AutoForm
16+
schema={schemaProvider}
17+
onSubmit={cy.stub().as("onSubmit")}
18+
withSubmit
19+
formProps={{
20+
className: "custom-form-class",
21+
"data-testid": "custom-form",
22+
onKeyDown: cy.stub().as("onKeyDown"),
23+
}}
24+
/>
25+
);
26+
27+
cy.get("form")
28+
.should("have.class", "custom-form-class")
29+
.and("have.attr", "data-testid", "custom-form");
30+
31+
cy.get('input[name="name"]').type("{enter}");
32+
cy.get("@onKeyDown").should("have.been.called");
33+
});
34+
35+
it("prevents form submission on enter key", () => {
36+
cy.mount(
37+
<AutoForm
38+
schema={schemaProvider}
39+
onSubmit={cy.stub().as("onSubmit")}
40+
withSubmit
41+
formProps={{
42+
onKeyDown: (e) => {
43+
if (e.key === "Enter") e.preventDefault();
44+
},
45+
}}
46+
/>
47+
);
48+
49+
cy.get('input[name="name"]').type("John Doe{enter}");
50+
cy.get("@onSubmit").should("not.have.been.called");
51+
});
52+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import React from "react";
2+
import { AutoForm } from "@autoform/shadcn/components/ui/autoform/AutoForm";
3+
import { ZodProvider } from "@autoform/zod";
4+
import { z } from "zod";
5+
import { TestWrapper } from "./utils";
6+
7+
describe("AutoForm Form Props Tests (shadcn)", () => {
8+
const schema = z.object({
9+
name: z.string(),
10+
});
11+
12+
const schemaProvider = new ZodProvider(schema);
13+
14+
it("applies custom form props", () => {
15+
cy.mount(
16+
<TestWrapper>
17+
<AutoForm
18+
schema={schemaProvider}
19+
onSubmit={cy.stub().as("onSubmit")}
20+
withSubmit
21+
formProps={{
22+
className: "custom-form-class",
23+
"data-testid": "custom-form",
24+
onKeyDown: cy.stub().as("onKeyDown"),
25+
}}
26+
/>
27+
</TestWrapper>
28+
);
29+
30+
cy.get("form")
31+
.should("have.class", "custom-form-class")
32+
.and("have.attr", "data-testid", "custom-form");
33+
34+
cy.get('input[name="name"]').type("{enter}");
35+
cy.get("@onKeyDown").should("have.been.called");
36+
});
37+
38+
it("prevents form submission on enter key", () => {
39+
cy.mount(
40+
<TestWrapper>
41+
<AutoForm
42+
schema={schemaProvider}
43+
onSubmit={cy.stub().as("onSubmit")}
44+
withSubmit
45+
formProps={{
46+
onKeyDown: (e) => {
47+
if (e.key === "Enter") e.preventDefault();
48+
},
49+
}}
50+
/>
51+
</TestWrapper>
52+
);
53+
54+
cy.get('input[name="name"]').type("John Doe{enter}");
55+
cy.get("@onSubmit").should("not.have.been.called");
56+
});
57+
});

package-lock.json

+11-11
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
+7-6
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,22 @@
11
import React from "react";
22
import { Box } from "@mantine/core";
33

4-
export const Form: React.FC<{
5-
onSubmit: (e: React.FormEvent) => void;
6-
children: React.ReactNode;
7-
}> = ({ onSubmit, children }) => {
4+
export const Form = React.forwardRef<
5+
HTMLFormElement,
6+
React.ComponentProps<"form">
7+
>(({ children, ...props }, ref) => {
88
return (
99
<Box
1010
component="form"
11-
onSubmit={onSubmit}
1211
style={{
1312
display: "flex",
1413
flexDirection: "column",
1514
gap: 15,
1615
}}
16+
ref={ref}
17+
{...props}
1718
>
1819
{children}
1920
</Box>
2021
);
21-
};
22+
});

packages/mui/src/components/Form.tsx

+6-6
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
import React from "react";
22
import Box from "@mui/material/Box";
33

4-
export const Form: React.FC<{
5-
onSubmit: (e: React.FormEvent) => void;
6-
children: React.ReactNode;
7-
}> = ({ onSubmit, children }) => {
4+
export const Form = React.forwardRef<
5+
HTMLFormElement,
6+
React.ComponentProps<"form">
7+
>(({ children, ...props }, ref) => {
88
return (
9-
<Box component="form" onSubmit={onSubmit} noValidate autoComplete="off">
9+
<Box component="form" ref={ref} noValidate autoComplete="off" {...props}>
1010
{children}
1111
</Box>
1212
);
13-
};
13+
});

0 commit comments

Comments
 (0)