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 theidof 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>.