Using Form

Almost every web application implements the C.R.U.D. model. So far, we’ve gone over several ways to Read data from your API using powerful declarative React components. The ability to Create and Update data is the purpose of the <Form /> component.

The <Form /> component provides a way to …

  • Use Model schemas to keep track of form fields
  • Use Model routes to avoid hard-coding API routes
  • Perform client-side form validations and populate error messages
  • Create or update data in your JSON API
  • Hook into form callbacks that give you granular control over data

…all while skipping a ton of boilerplate!

Contents

  1. Basic Example
  2. Available Props
  3. The Form Object
    1. Field Props
    2. Submit Props
    3. Other Form Object Properties
  4. Creating Resources
  5. Updating Resources
  6. Error Handling
  7. Form Events
  8. Summary

Basic Example

If you can read JSX, you can learn a lot about how the <Form /> component operates by viewing how it’s used. Here’s a basic example of the <Form /> component in a typical sign-up form.

import ReactiveRecord, { Form } from "reactiverecord"
const User = ReactiveRecord.model("User")
...
return (
  <Form for={new User()}>
    {fields => (
      <Fragment>
        <Input {...fields.full_name} />
        <Input {...fields.email} />
        <Input {...fields.password} />
        <Button {...fields.submit}>Sign Up</Button>
      </Fragment>
    )}
  </Form>
)
Generated onSubmit()
<form>
  <label>
    Full Name <input />
  </label>
  <label>
    Email <input />
  </label>
  <label>
    Password <input />
  </label>
  <button>Sign Up</button>
</form>
POST /users 201 Created

{
  "full_name": "General Tzo",
  "email": "general@tzo.com",
  "password": "chickens-23"
}

Amazing! Let’s talk about what’s written here.

  1. By passing in a new User() instance as the for prop, we’re telling the <Form /> component to expect fields based on the User model’s schema.
  2. Because it’s a new user, it’s assumed the resource doesn’t exist, which means the appropriate form method is POST.
  3. We know the route configuration from the model class, so the form action will be /users.
  4. Like other Reactive Record components, the <Form /> component expects a function as its child. The function received a form object, which contains properties that help build the individual form fields. We can pass those properties directly to our <Input /> components, which we’ll go over in detail later.

Available Props

Prop Type Description Required
children Function Function receives one argument: a Reactive Record form object. It contains properties named after the given model’s schema, and is used to manage form controls within the form. You can read more about what’s available in the form object below. Yes
for Model instance Pass in the resource being acted upon. This resource must be an instance of a class which inherits from Model. Example: new User(). Yes
beforeValidation Promise Called before form validation occurs after form is submitted. The given Promise receives the form’s internal fields object, which contains refs to mounted form controls. At this point in the form submission, no data validation has occurred. You can use this callback as an opportunity to edit form values before validation occurs. The given Promise must be resolved in order to continue form submission. No
afterValidationFail Function Called after all validation has occurred, but at least one field has failed validation after form submission. The given function receives an object containing all field values. No
beforeSave Promise Called after form validation succeeds and the form is ready for final submission. The given Promise receives an object containing all field values which will be submitted. You can use this callback as an opportunity to cancel form submission and do something else with the form data, or to edit fields just before an API request is made. The given Promise must be resolved with the original or mutated form values object in order to continue form submission. No
afterSave Function Called after an API request succeeds with a successful HTTP status code (greater than 199 and less than 400). The function receives the latest version of the resource being acted upon. This callback is called immediately before the next action is dispatched, thereby triggering a re-render. No
afterRollback Function Called after an API request fails due to an HTTP status code (greater than or equal to 400), or an error that occurred while processing the response. The given function receives a resource when available or the resulting error. This callback is called immediately before the next action is dispatched, thereby triggering a re-render. No
builder Function Used to build field props for custom form controls. Read more about the builder API in the next guide. No
query Object|String Used to add extra parameters not in the model’s schema to the request body. The query can either be an object, which will be serialized, or a query string.
Examples:
{ utm_source: 'google', utm_medium: 'cpc' }

utm_source=google&utm_medium=cpc
No
* any Any props given that are not listed above will be passed directly to the inner <form> DOM element, except onSubmit(), which is ignored. Example: className, aria-*. No

The Form Object

The function passed in as children for the <Form /> component receives an object containing properties used to build form controls within the form. The properties map directly to the form resource’s schema. For instance, if the schema for a model called Session is:

Session.schema = {
  username: String,
  password: String
}

… the resulting form object would contain:

{
  username: {},
  password: {},
  submit: {},
  submitting: false,
  validating: false,
  fieldsFor: ƒ()
}

There are additional properties in the above object that are not in the schema, which we will go over shortly. Let’s start with the first property, username. It contains individual field props.

Field Props

The <Form /> component builds field props for each attribute in the schema. These field props can be passed directly to form controls to render the correct data. Here is a list of the default field props given for each schema attribute:

Attribute Value
ref Function needed to track the form control element. Pass directly to the form control.
labelText Text describing the form control. By default, this is the humanized name of the attribute. An attribute called email will by default have the label text “Email.” It can be overridden by configuring the model schema.
defaultValue Contains the default value for the attribute. If the resource is existing, expect the existing value to be present. Otherwise, the default value will be null or the default value set in the model schema.
errorText Contains the specific error text related to the form control, either from client-side validations or an API response.
validators If the attribute has validators, they will be present here.

Submit Props

The form object contains a submit property, which can be passed directly to a <button> element, which submits the form. It contains the following attributes:

Attribute Value
disabled True only while the form is submitting or validating to prevent consecutive form submissions or “rage clicking.”
children The value is “Saving” while the form is submitting, and is otherwise undefined. Use this to easily override the button children while an API request is made.

Other Form Object Properties

Attribute Value
submitting True only while an API request is made.
validating True only while field validations are occurring.
fieldsFor Function used to create fields for nested attributes. Learn more about using fieldsFor later.

Creating Resources

Updating Resources

Error Handling

Form Events

Summary