カスタム表示ブロックを作る

NocoBase では、ブロックはページ上のコンテンツ領域です。この例では BlockModel を使って最もシンプルなカスタムブロックを作る方法を示します。画面上で HTML コンテンツを編集でき、ユーザーが設定パネルからブロックの表示内容を変更できます。

これは FlowEngine を使う最初の例で、BlockModelrenderComponentregisterFlowuiSchema を使用します。

前提知識

以下の内容を事前に理解しておくと、開発がスムーズになります:

最終的な効果

「Simple block」ブロックを作ります:

  • 「ブロックの追加」メニューに表示される
  • ユーザーが設定した HTML コンテンツをレンダリング
  • 設定パネル(registerFlow + uiSchema)でユーザーが HTML を編集可能

完全なソースコードは @nocobase-example/plugin-simple-block を参照してください。ローカルで動作確認したい場合:

yarn pm enable @nocobase-example/plugin-simple-block

以下、ゼロからこのプラグインを構築していきます。

ステップ1:プラグインスケルトンの作成

リポジトリのルートで実行します:

yarn pm create @my-project/plugin-simple-block

packages/plugins/@my-project/plugin-simple-block 配下に基本的なファイル構成が生成されます。詳しくははじめてのプラグインを書くをご覧ください。

ステップ2:ブロックモデルの作成

src/client-v2/models/SimpleBlockModel.tsx を新規作成します。これがプラグインの中核で、ブロックのレンダリング方法と設定方法を定義します。

// src/client-v2/models/SimpleBlockModel.tsx
import React from 'react';
import { BlockModel } from '@nocobase/client-v2';
import { tExpr } from '../locale';

export class SimpleBlockModel extends BlockModel {
  renderComponent() {
    return <div dangerouslySetInnerHTML={{ __html: this.props.html }} />;
  }
}

// 「ブロックの追加」メニューでの表示名を設定
SimpleBlockModel.define({
  label: tExpr('Simple block'),
});

// 設定パネルを登録し、ユーザーが HTML コンテンツを編集可能にする
SimpleBlockModel.registerFlow({
  key: 'flow1',
  title: tExpr('Simple Block Flow'),
  on: 'beforeRender', // レンダリング前に実行
  steps: {
    editHtml: {
      title: tExpr('Edit HTML Content'),
      // uiSchema で設定パネルのフォーム UI を定義
      uiSchema: {
        html: {
          type: 'string',
          title: tExpr('HTML Content'),
          'x-decorator': 'FormItem',
          'x-component': 'Input.TextArea',
        },
      },
      // 設定パネルのデフォルト値
      defaultParams: {
        html: `<h3>This is a simple block</h3>
<p>You can edit the HTML content.</p>`,
      },
      // 設定パネルの値を model の props に書き込む
      handler(ctx, params) {
        ctx.model.props.html = params.html;
      },
    },
  },
});

重要なポイント:

  • renderComponent() — ブロックの UI をレンダリングし、this.props.html から HTML コンテンツを読み取る
  • define() — 「ブロックの追加」メニューでの表示名を設定。tExpr() は遅延翻訳に使用(define() はモジュール読み込み時に実行され、その時点では i18n がまだ初期化されていないため)
  • registerFlow() — 設定パネルを追加。uiSchema で JSON Schema 形式のフォームを定義(構文は UI Schema を参照)、handler でユーザーが入力した値を ctx.model.props に設定し、renderComponent() から読み取れるようにする

ステップ3:多言語ファイルの追加

プラグインの src/locale/ 配下の翻訳ファイルを編集し、tExpr() で使用する key の翻訳を追加します:

// src/locale/zh-CN.json
{
  "Simple block": "简单区块",
  "Simple Block Flow": "简单区块配置",
  "Edit HTML Content": "编辑 HTML 内容",
  "HTML Content": "HTML 内容"
}
// src/locale/en-US.json
{
  "Simple block": "Simple block",
  "Simple Block Flow": "Simple Block Flow",
  "Edit HTML Content": "Edit HTML Content",
  "HTML Content": "HTML Content"
}
注意

初めて言語ファイルを追加した場合、アプリの再起動が必要です。

翻訳ファイルの書き方と tExpr() のその他の使い方については、i18n 国際化をご覧ください。

ステップ4:プラグインへの登録

src/client-v2/plugin.tsx を編集し、registerModelLoaders で遅延読み込み登録します:

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

export class PluginSimpleBlockClient extends Plugin {
  async load() {
    this.flowEngine.registerModelLoaders({
      SimpleBlockModel: {
        // 遅延読み込み。初めて使用される時にモジュールをロード
        loader: () => import('./models/SimpleBlockModel'),
      },
    });
  }
}

export default PluginSimpleBlockClient;

registerModelLoaders は動的インポートを使用し、モデルコードは実際に必要になった時に初めてロードされます。これが推奨される登録方法です。

ステップ5:プラグインの有効化

yarn pm enable @my-project/plugin-simple-block

有効化後、新しいページを作成して「ブロックの追加」をクリックすると「Simple block」が表示されます。追加後、ブロックの設定ボタンをクリックして HTML コンテンツを編集できます。

完全なソースコード

まとめ

この例で使用した機能:

機能使い方ドキュメント
ブロックレンダリングBlockModel + renderComponent()FlowEngine → ブロック拡張
メニュー登録define({ label })FlowEngine 概要
設定パネルregisterFlow() + uiSchemaFlowEngine 概要
モデル登録registerModelLoaders(遅延読み込み)Plugin プラグイン
遅延翻訳tExpr()i18n 国際化

関連リンク