Rendering Forms
How to render forms and their components.
Once you have a formConfig
, the @rilaykit/forms
package provides a set of components to render it. Remember, these components rely on the mandatory renderers you configured on your ril
instance.
The <Form>
Component
The <Form>
component is the root of your form. It's a stateful component that manages the entire form lifecycle.
import { Form } from '@rilaykit/forms';
import { formConfig } from '@/config/my-form';
function MyFormPage() {
const handleSubmit = (data) => {
// This is called only when the form is valid
console.log('Form submitted:', data);
};
const handleFieldChange = (fieldId, value, allData) => {
console.log(`Field '${fieldId}' changed to:`, value);
console.log('Current form data:', allData);
};
return (
<Form
formConfig={formConfig}
onSubmit={handleSubmit}
onFieldChange={handleFieldChange}
defaultValues={{ firstName: 'Jane' }}
>
{/* Form layout components go here */}
</Form>
);
}
Props
formConfig
: The configuration object generated by theformBuilder
.onSubmit
: A callback function that receives the form data when the form is successfully submitted. It will not be called if the form is invalid.onFieldChange
(optional): A callback that fires whenever any field's value changes. It receives thefieldId
, the newvalue
, and a snapshot of the entire form's data.defaultValues
(optional): An object to populate the form with initial values. The keys should match theid
of your fields.
Layout Components
Inside the <Form>
component, you can use layout components to control how the fields are rendered.
<FormBody>
This is the simplest way to render your form. The <FormBody>
component will iterate through the rows
in your formConfig
and render them using your registered FormBodyRenderer
and FormRowRenderer
.
<Form {...props}>
<FormBody />
<FormSubmitButton>Submit</FormSubmitButton>
</Form>
<FormField>
for Custom Layouts
If you need a fully custom layout that doesn't follow the row structure defined in your formConfig
, you can use the <FormField>
component. This allows you to place any field, anywhere you want.
<Form {...props}>
<div className="my-custom-layout">
<div className="sidebar">
<FormField fieldId="profilePicture" />
</div>
<div className="main-content">
<h2>User Details</h2>
<FormField fieldId="firstName" />
<FormField fieldId="lastName" />
<hr />
<FormField fieldId="bio" />
</div>
</div>
<FormSubmitButton>Save Changes</FormSubmitButton>
</Form>
When using <FormField>
, you are responsible for the layout. The FormRowRenderer
is not used. This gives you maximum flexibility.
<FormSubmitButton>
This is a smart component that handles form submission using your FormSubmitButtonRenderer
. It is automatically disabled if the form is invalid or currently submitting. You can customize its content via its children
.
<FormSubmitButton>
{(props) => (
props.isSubmitting ? 'Saving...' : 'Save Profile'
)}
</FormSubmitButton>
The children
can also be a simple string or element, like <FormSubmitButton>Submit</FormSubmitButton>
.