Rilaykit Logorilaykit ✨
Forms

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 the formBuilder.
  • 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 the fieldId, the new value, and a snapshot of the entire form's data.
  • defaultValues (optional): An object to populate the form with initial values. The keys should match the id 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>.