8000 Frontend: Forms · metabase/metabase Wiki · GitHub
[go: up one dir, main page]

Skip to content

Frontend: Forms

Tom Robinson edited this page Jun 11, 2020 · 4 revisions

Metabase includes a comprehensive custom React and redux-form based form library. It also integrates with Metabase's Entities system.

The core React component of the system is metabase/containers/Form.

Form Definitions

Form definitions can be provided in two different ways, with a JavaScript-based form definition object, or inline React <FormField> elements.

Pass a form definition to the form prop:

<Form
  form={{
    fields: [
      {
        name: "email",
        placeholder: "bob@metabase.com",
        validate: validate.required().email(),
      },
      {
        name: "password",
        type: "password",
        validate: validate.required().passwordComplexity(),
      },
    ],
  }}
  onSubmit={values => alert(JSON.stringify(values))}
/>

If <Form> doesn't have any children elements then it will uses the metabase/components/StandardLayout component to provide a default form layout.

The schema for this object is defined in Form.jsx.

fields and initial (for initial values) can be provided directly or as functions that dynamically compute them based on the current form state and additional props.

{
  "fields": (values) => [
    { name: "a", type:  }

initial, normalize, and validate properties can be provided at the top-level, or per-field. They can also be provided as props to the <Form> and <FormField> components For definitions can be provided

Custom Layout

Form definition can also be provided via <FormField> React elements (exported from the same metabase/containers/Form module), which will also serve as the layout (this uses the metabase/components/CustomLayout)

import Form, { FormField, FormFooter } from "metabase/containers/Form";

<Form onSubmit={values => alert(JSON.stringify(values))}>
  <FormField
    name="email"
    placeholder="bob@metabase.com"
    validate={validate.required()}
  />
  <FormField
    name="password"
    type="password"
    validate={validate.required().passwordComplexity()}
  />
  <FormFooter />
</Form>

You can also provide both the form prop and children <FormField> elements, in which case the form prop will be merged with the <FormField>s' props.

Custom Widgets

Built-in field types are defined in metabase/components/form/FormWidget. You can also provide a React component as the type property.

Validation

You might have noticed the validate API above. These are simple chainable validators compatible with this form library, and are provided by metabase/lib/validate. You can add additional validators in that file.

Server-side validation and other errors are returned in a standard format understood by <Form>.

Field-level errors:

{ "errors": { "field_name": "error message" } }

Top-level errors:

{ "message": "error message" }

Integration with Entities

The Form library is integrated with Metabase's Entities system (via the EntityForm component), so that every entity includes a Form component that can be used like so:

<Users.Form />

which uses the default form defined on the entity, e.x.

const Users = createEntity({
  name: "users",
  path: "/api/user",

  form: {
    fields: [
      { name: "email" }
    ]
  }

  // Alternatively, it will take the first form from the `forms` object:
  // form: {
  //  default: {
  //    fields: [
  //      { name: "email" }
  //    ]
  //  }
  // }
}

You can also explicitly pass a different form object:

<Users.Form form={Users.forms.passwordReset} />

Entity Forms will automatically be wired up to the correct REST endpoints for creating or updating entities.

If you need to load an object first, they compose nicely with the Entities Loader render prop:

<Users.Load id={props.params.userId}>
  {({ user }) => <Users.Form user={user} />}
</Users.Load>

Or higher-order component:

Users.load({ id: (state, props) => props.params.userId })(Users.Form)

Clone this wiki locally

0