Form

This is the official documentation of Forest Admin Cloud.

Frequently, it is necessary to request information before proceeding with the execution of an action. In Forest Admin, this occurs through a form that pops up before the action is executed. For example, you might need to explain why you need to block a user account or decide how much to charge a user's credit card.

TL;DR

Ensure you update the collection and action names as needed.

index.ts
import type { Agent } from '@forestadmin/forest-cloud';
import { Schema } from '../typings';

export default function customizeAgent(agent: Agent<Schema>) {
  agent.customizeCollection('users', collection =>
    collection.addAction('A sample action', {
      scope: 'Single',
      form: [{
        label: 'field',
        description: 'some description...',
        type: 'String',
      }],
      execute: async (context) => {
        const { field } = context.formValues;
        // Your business logic here.
      },
    }),
  );
}

To make the code easier to read, all the code snippets below should be wrapped in the following code. Ensure you update the collection and action names as needed.

import type { Agent } from '@forestadmin/forest-cloud';
import { Schema } from '../typings';

export default function customizeAgent(agent: Agent<Schema>) {
  agent.customizeCollection('contacts', collection =>
    collection.addAction('Ban contact', {
      scope: 'Single',
      // Insert the code snippet here.
    }),
  );
}

Creating a static form

Add the form key in the action definition to open a form before executing the action:

form: [{
  label: 'reason',
  type: 'String',
}],

Arguments:

  • Form [Object]: A JavaScript array that contains a list of JavaScript Objects, each representing a field to add in the form.

    • label* String: The name of the field.

    • type* String: The type of the field. Expected value:

    • collectionName String: Required when type is Collection.

    • defaultValueany: Set the default value of the field.

    • description String: A description that explains the field's function and usage for clarity.

    • enumValues [String]: Required when type is Enum.

    • isReadOnlyBoolean: Specifies whether the field is mandatory or not. Default false.

    • isRequired Boolean: Specifies whether the field is mandatory or not. Default false.

    • widget String: Customize the widget to display the field.

Creating a dynamic form

To create a form that changes based on the values of other fields, use a function instead of a static value for properties that support dynamic values. Both synchronous and asynchronous functions are supported. These functions have the same context argument as the execute() function.

Properties that support dynamic values:

  • isRequired

  • isReadOnly

  • defaultValue

  • description

  • enumValues if type is Enum

  • collectionName if type is Collection

When setting up a dynamic form, you can use two additional properties:

  • if: Display the field if the condition is met.

  • value: Sets the field's current value.

Widgets properties that support dynamic values:

  • options

  • min

  • max

  • step

Retrieving form values

Within the execute() function, you can access and use the form input values provided by the user who initiated the action by accessing the formValues attribute from the context.

execute: async (context) => {
  const { reason } = context.formValues;
},

Examples

To make the code easier to read, all the code snippets below should be wrapped in the following code. Ensure you update the collection and action names as needed.

import type { Agent } from '@forestadmin/forest-cloud';
import { Schema } from '../typings';

export default function customizeAgent(agent: Agent<Schema>) {
  agent.customizeCollection('contacts', (collection) => {
    // Insert the code snippet here.
  });
}

Configuring a Relationship as a Form Field

When you use the Collection type, you can link to any record from any collection. This link uses the record's primary key as its value.

The value is stored in an array to handle composite primary keys. For non-composite keys, the array contains one value.

collection.addAction('Assign ticket', {
  scope: 'Single',
  form: [{
    label: 'Assignee',
    description: 'The user to assign the ticket to',
    type: 'Collection',
    collectionName: 'user',
    isRequired: true,
  }],
  execute: async (context, resultBuilder) => {
    const [userId] = context.formValues.Assignee;
    // ...
  },
});

Making a field required dynamically

In this example, we request to fill the reason field if the amount of the credit card charge exceeds 1000.

collection.addAction('Charge credit card', {
  scope: 'Single',
  form: [{
    label: 'amount',
    type: 'Number',
    isRequired: true,
  }, {
    label: 'reason',
    type: 'String',
    isRequired: context => context.formValues['amount'] > 1000,
  }],
  execute: async (context) => {
    // ...
  },
});

Last updated