Action Extension

In NocoBase, an Action is a button within a block that triggers business logic — such as "Create", "Edit", "Delete", etc. By extending the ActionModel base class, you can add custom action buttons.

Action Scenes

Each action needs to declare the scene in which it appears, specified via the static scene property:

SceneValueDescription
collectionActionSceneEnum.collectionOperates on the collection, e.g., "Create" button
recordActionSceneEnum.recordOperates on a single record, e.g., "Edit", "Delete" buttons
bothActionSceneEnum.bothAvailable in both scenes
allActionSceneEnum.allAvailable in all scenes (including special contexts like dialogs)

Examples

Collection-Level Action

Operates on the entire collection, appears in the action bar at the top of the block:

// models/SimpleCollectionActionModel.tsx
import { ActionModel, ActionSceneEnum } from '@nocobase/client-v2';
import { ButtonProps } from 'antd';
import { tExpr } from '@nocobase/flow-engine';

export class SimpleCollectionActionModel extends ActionModel {
  static scene = ActionSceneEnum.collection;

  defaultProps: ButtonProps = {
    children: tExpr('Simple collection action'),
  };
}

SimpleCollectionActionModel.define({
  label: tExpr('Simple collection action'),
});

Record-Level Action

Operates on a single record, appears in the action column of each table row:

// models/SimpleRecordActionModel.tsx
import { ActionModel, ActionSceneEnum } from '@nocobase/client-v2';
import { ButtonProps } from 'antd';
import { tExpr } from '@nocobase/flow-engine';

export class SimpleRecordActionModel extends ActionModel {
  static scene = ActionSceneEnum.record;

  defaultProps: ButtonProps = {
    children: tExpr('Simple record action'),
  };
}

SimpleRecordActionModel.define({
  label: tExpr('Simple record action'),
});

Available in Both Scenes

If the action doesn't distinguish between scenes, use ActionSceneEnum.both:

// models/SimpleBothActionModel.tsx
import { ActionModel, ActionSceneEnum } from '@nocobase/client-v2';
import { ButtonProps } from 'antd';
import { tExpr } from '@nocobase/flow-engine';

export class SimpleBothActionModel extends ActionModel {
  static scene = ActionSceneEnum.both;

  defaultProps: ButtonProps = {
    children: tExpr('Simple both action'),
  };
}

SimpleBothActionModel.define({
  label: tExpr('Simple both action'),
});

The structure of all three patterns is identical — the only differences are the static scene value and the button text in defaultProps.

Registering Actions

Register with registerModelLoaders for lazy loading in the Plugin's load() method:

// plugin.tsx
import { Plugin } from '@nocobase/client-v2';

export class PluginSimpleActionClient extends Plugin {
  async load() {
    this.flowEngine.registerModelLoaders({
      SimpleCollectionActionModel: {
        loader: () => import('./models/SimpleCollectionActionModel'),
      },
      SimpleRecordActionModel: {
        loader: () => import('./models/SimpleRecordActionModel'),
      },
      SimpleBothActionModel: {
        loader: () => import('./models/SimpleBothActionModel'),
      },
    });
  }
}

After registration, you can add your custom action buttons in the block's "Configure actions" menu.

Full Source Code