iceform
Use forms with or without client-side JavaScript--no code duplication required!
Powered by formxtra.
iceform
defines two routes in the backend component: the API route used by client-side JavaScript, and the action
route used by the form when client-side JavaScript is not available.
First, define the common business logic:
// [src/]handlers/greet.ts
import {NextApiHandler} from 'next';
export const greet: NextApiHandler = async (req, res) => {
const { name } = req.body;
res.status(202).json({
name: `Hello ${name}`,
});
};
Then define the API route:
// [src/]pages/api/greet.ts
import * as Iceform from '@modal-sh/iceform-next';
import { greet } from '@/handlers/greet';
const handler = Iceform.action.wrapApiHandler({ fn: greet });
// you can extend the route config by passing an extra argument
export const config = Iceform.action.getApiConfig();
export default handler;
Next, define the action route:
// [src/]pages/a/greet.ts
//
// (we use `/a/**` routes but feel free to use something else)
import {NextPage} from 'next';
import * as Iceform from '@modal-sh/iceform-next';
import {greet} from '@/handlers/greet';
// render anything while form is being processed, or just return an empty component here
const ActionGreetPage: NextPage = () => null;
export default ActionGreetPage;
export const getServerSideProps = Iceform.action.getServerSideProps({ fn: greet });
Lastly, define the form page:
// [src/]pages/form.tsx
import * as React from 'react';
import * as Iceform from '@modal-sh/iceform-next';
const FormPage: Iceform.NextPage = ({
req,
res,
}) => {
const {response, ...isoformProps} = Iceform.useResponse(res);
// you may access the server-side body on `res.body`
const [responseData, setResponseData] = React.useState<unknown>();
React.useEffect(() => {
// response.bodyUsed might be undefined, so we use a strict comparison
if (response?.bodyUsed === false) {
response?.json().then((responseData) => {
setResponseData(responseData);
});
}
}, [response]);
// set up your form fields
return (
<Iceform.Form
{...isoformProps}
method="post"
action="/a/greet"
clientAction="/api/greet"
>
<input
type="text"
name="name"
/>
<button
type="submit"
>
Submit
</button>
</Iceform.Form>
)
};
export const getServerSideProps = Iceform.destination.getServerSideProps();
export default GreetPage;
In theory, any API route may have a corresponding action route.
accept-charset=""
attribute support