Examples

The Friage.Form component is used to render a form in your application. You can use it to collect user information, feedback, or any other data you need. As with other Frigade components, a Form can contain multiple steps, each with its own fields and buttons.

The Form SDK is built on top of react-hook-form, which means you can use the majority of its features in your forms.

Simple Modal Form

import * as Frigade from '@frigade/react';

const App = () => {
  return (
    <Frigade.Form
      flowId="flow_laJhda4sgJCdsCy6"
      // This will open the form in a modal
      as={Frigade.Dialog}
    />
  )
}

Supported Field Types

The component supports the following field types:

  • select
  • radio
  • text
  • textarea

You can also define custom field types using the fieldTypes prop.

For instance, if you want to build a custom field type called calendar:

import { Form, FormFieldProps } from '@frigade/react'

function CalendarField({ field, submit }: FormFieldProps) {
  return (
   <div>
     <input type="date" onChange={field.onChange} value={field.value} />
   </div>
  )
}

 // ...

 <Form flowId="my-flow-id" fieldTypes={{ calendar: CalendarField }} />

It is also possible to conditionally render a field based on the value of another field by using the formContext provided by react-hook-forms. For instance, if you want a custom field called company-size to show up when a user selects company in the customer-type field:

import { Form, type FormFieldProps, SelectField } from "@frigade/react";

<Form
  flowId="myflowid"
  fieldTypes={{
    "company-size": (props: FormFieldProps) => {
      const customerTypeValue = props.formContext.watch("customer-type");

      if (customerTypeValue !== "company") {
        return null;
      }

      return (
        <div>My custom conditional field</div>
      );
    },
  }}
/>

Conditional Forms

If you want a form to conditionally skip a step based on the result of a previous step, you can use the visibilityCriteria property in the step configuration. For instance, the example below will jump directly to page 3 if the user picks a specific option on the first page/step:

steps:
  - id: page-1
    title: This is page 1
    primaryButtonTitle: Next
    fields:
      - id: test-radio-1
        type: radio
        label: Radio group
        options:
          - label: Go to page 3
            value: x
          - label: Continue to page 2
            value: y
  - id: page-2
    title: This is page 2
    primaryButtonTitle: Next
    visibilityCriteria: user.flowStepData("flow_fpJlqkbl", "page-1", "test-radio-1") != "x"
    fields:
      - id: test-text
        type: text
        label: Text field
  - id: page-3
    title: This is page 3
    primaryButtonTitle: Finish
    fields:
      - id: test-radio-3
        type: radio
        label: Radio group
        options:
          - label: Radio 1
            value: 1
          - label: Radio 2
            value: 2
          - label: Radio 3
            value: 3

visibilityCriteria will work with both form data or any other Targeting condition.

Flow Configuration

The following props are available in the YAML Config defined in the Frigade Dashboard:

steps
array
The individual steps/pages of the form
steps[].id
string
Unique identifier for the step. Do not change this once the step has been created.
steps[].title
string
The title of the step
steps[].subtitle
string
The description of the step
steps[].imageUri
string
Url to an image to display in the step
steps[].videoUri
string
Url to a video to display in the step such as YouTube, Vimeo, or a direct link to an mp4 file
steps[].primaryButton
object
Config for the primary button in this step.
steps[].primaryButton.action
string
Primary button action. (defaults to step.complete).
Possible values: flow.back, flow.complete, flow.forward, flow.restart, flow.skip, flow.start, step.complete, step.reset, step.start
steps[].primaryButton.target
string
Primary button URI target (defaults to _self).
steps[].primaryButton.title
string
Primary button title. If omitted, the primary button will not be shown.
steps[].primaryButton.uri
string
Primary button URI.
steps[].primaryButtonTitle
string
Deprecated: use primaryButton.title instead. The title of the primary button
steps[].primaryButtonUri
string
Deprecated: use primaryButton.uri instead. The url to open when the primary button is clicked
steps[].primaryButtonUriTarget
string
Deprecated: use primaryButton.target instead. The target of the primary button url (default: _blank; use _self to open in the same window). Setting it to # will open the existing page and dismiss any Frigade modals.
steps[].secondaryButton
object
Config for the secondary button in this step.
steps[].secondaryButton.action
string
Secondary button action. (defaults to step.complete).
Possible values: flow.back, flow.complete, flow.forward, flow.restart, flow.skip, flow.start, step.complete, step.reset, step.start
steps[].secondaryButton.target
string
Secondary button URI target (defaults to _self).
steps[].secondaryButton.title
string
Secondary button title. If omitted, the secondary button will not be shown.
steps[].secondaryButton.uri
string
Secondary button URI.
steps[].secondaryButtonTitle
string
Deprecated: use secondaryButton.title instead. The title of the secondary button
steps[].secondaryButtonUri
string
Deprecated: use secondaryButton.uri instead. The url to open when the secondary button is clicked
steps[].secondaryButtonUriTarget
string
Deprecated: use secondaryButton.target instead. The target of the secondary button url (default: _blank; use _self to open in the same window). Setting it to # will open the existing page and dismiss any Frigade modals.
steps[].completionCriteria
string
Targeting that automatically completes the step. E.g.: user.property(‘connectedBank’) == true
steps[].startCriteria
string
Targeting that automatically blocks the step from starting until it becomes true. E.g.: user.property(‘connectedBank’) == true
steps[].visibilityCriteria
string
Targeting that automatically shows the step when it becomes true. E.g.: user.property(‘connectedBank’) == true
steps[].props
object
Override the default UI props for the corresponding component
steps[].fields
array
The data contained on the form step, typically text input boxes, multiple choice questions, etc.
steps[].fields[].id
string
Unique identifier for the step. Do not change this once the step has been created.
steps[].fields[].label
string
The label of the field
steps[].fields[].type
string
The type of the field, following standard naming conventions: text, textarea, select. If you are using custom form field types, the name here should match it.
steps[].fields[].placeholder
string
The placeholder of the field
steps[].fields[].maxLength
integer
The maximum length of the field
steps[].fields[].required
any
Whether the field is required or not. Use a string here to show a custom error message.
steps[].fields[].options
array
The options for the field. Only used for select fields.
steps[].fields[].options[].label
string
The label of the option
steps[].fields[].options[].value
any
The value of the option
steps[].fields[].pattern
object
The validation rules for the field. See documentation for more information.
steps[].fields[].pattern.value
string
Regex pattern to match the field against
steps[].fields[].pattern.message
string
The error message to display if the pattern does not match

React Component Props

as

Optional as: ElementType<any, keyof IntrinsicElements>

Optional component type to wrap the child components in. Use theas={Box} component for inline placement or the as={Dialog} component for modal placement. If you want to wrap the Flow in a custom component (such as your own modal), you can pass the custom component here.


dismissible

Optional dismissible: boolean

Whether the Flow is dismissible or not


fieldTypes

Optional fieldTypes: FieldTypes

Custom field types to be used in the Form. You can use this to build your own custom form fields in a Form.

For example, if you want to use a custom field type called calendar:

import { Form, FormFieldProps } from '@frigade/react'

function CalendarField({ field, submit }: FormFieldProps) {
  return (
   <div>
     <input type="date" onChange={field.onChange} value={field.value} />
   </div>
  )
}

 // ...

 <Form flowId="my-flow-id" fieldTypes={{ calendar: CalendarField }} />


flowId

flowId: string

The Flow ID to render. You can find the Flow ID in the Frigade dashboard.


forceMount

Optional forceMount: boolean

If true, the Flow will be mounted even if it has already been completed or dismissed. However, if the user does not match the Flow’s targeting, the Flow will not be mounted.


onComplete

Optional onComplete: FlowHandlerProp

Handler for when the Flow is completed. If this function a promise that evaluates to false, the Flow will not be marked as completed.


onDismiss

Optional onDismiss: FlowHandlerProp

Handler for when the Flow is dismissed. If this function a promise that evaluates to false, the Flow will not be marked as dismissed.


onPrimary

Optional onPrimary: StepHandlerProp

Handler for when primary button is clicked. If this function a promise that evaluates to false, the step will not be automatically completed when clicked.


onSecondary

Optional onSecondary: StepHandlerProp

Handler for when secondary button is clicked. If this function a promise that evaluates to false, the step will not be automatically completed when clicked.


variables

Optional variables: Record<string, unknown>

Variables to pass to the Flow. You can use variables in the Flow configuration to customize copy. For instance, you can use title: Hello, ${name}! in the Flow configuration and pass variables={{name: 'John'}} to customize the copy.

View definition