Faire un bloc d'affichage personnalisé

Dans NocoBase, un bloc est une zone de contenu sur la page. Cet exemple montre comment créer un bloc personnalisé minimal avec BlockModel — il prend en charge l'édition de contenu HTML directement dans l'interface, l'utilisateur pouvant modifier le contenu affiché via le panneau de configuration.

C'est le premier exemple impliquant FlowEngine ; il fait intervenir BlockModel, renderComponent, registerFlow et uiSchema.

Lecture préalable

Il est conseillé de connaître les contenus suivants pour faciliter le développement :

Résultat final

Nous allons créer un bloc « Simple block » :

  • Apparaît dans le menu « Ajouter un bloc »
  • Affiche le contenu HTML configuré par l'utilisateur
  • Permet à l'utilisateur d'éditer le HTML via le panneau de configuration (registerFlow + uiSchema)

Code source complet : @nocobase-example/plugin-simple-block. Pour le faire tourner directement en local :

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

Construisons ce plugin pas à pas, à partir de zéro.

Étape 1 : créer le squelette du plugin

À la racine du dépôt :

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

Cela génère la structure de fichiers de base sous packages/plugins/@my-project/plugin-simple-block. Voir Écrire votre premier plugin pour les détails.

Étape 2 : créer le modèle de bloc

Créez src/client-v2/models/SimpleBlockModel.tsx. C'est le cœur du plugin — il définit la façon dont le bloc s'affiche et se configure.

// 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 }} />;
  }
}

// Définit le nom affiché du bloc dans le menu « Ajouter un bloc »
SimpleBlockModel.define({
  label: tExpr('Simple block'),
});

// Enregistre le panneau de configuration pour permettre à l'utilisateur d'éditer le HTML
SimpleBlockModel.registerFlow({
  key: 'flow1',
  title: tExpr('Simple Block Flow'),
  on: 'beforeRender', // S'exécute avant le rendu
  steps: {
    editHtml: {
      title: tExpr('Edit HTML Content'),
      // uiSchema définit l'UI du formulaire du panneau de configuration
      uiSchema: {
        html: {
          type: 'string',
          title: tExpr('HTML Content'),
          'x-decorator': 'FormItem',
          'x-component': 'Input.TextArea',
        },
      },
      // Valeurs par défaut du panneau de configuration
      defaultParams: {
        html: `<h3>This is a simple block</h3>
<p>You can edit the HTML content.</p>`,
      },
      // Écrit la valeur du panneau de configuration dans les props du modèle
      handler(ctx, params) {
        ctx.model.props.html = params.html;
      },
    },
  },
});

Quelques points clés :

  • renderComponent() — rend l'UI du bloc en lisant this.props.html
  • define() — définit le nom affiché dans le menu « Ajouter un bloc ». tExpr() sert à la traduction différée car define() s'exécute au chargement du module, alors qu'i18n n'est pas encore initialisé
  • registerFlow() — ajoute un panneau de configuration. uiSchema définit le formulaire avec JSON Schema (syntaxe : voir UI Schema), handler écrit la valeur saisie par l'utilisateur dans ctx.model.props, lue ensuite par renderComponent()

Étape 3 : ajouter les fichiers de traduction

Modifiez les fichiers de traduction sous src/locale/ du plugin pour ajouter les clés utilisées par tExpr() :

// 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"
}
Attention

L'ajout initial des fichiers de langue nécessite un redémarrage de l'application pour prendre effet.

Pour l'écriture des fichiers de traduction et plus d'utilisations de tExpr(), voir Internationalisation i18n.

Étape 4 : enregistrer dans le plugin

Modifiez src/client-v2/plugin.tsx et utilisez registerModelLoaders pour le chargement à la demande :

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

export class PluginSimpleBlockClient extends Plugin {
  async load() {
    this.flowEngine.registerModelLoaders({
      SimpleBlockModel: {
        // Chargement à la demande : ne charge le module qu'à la première utilisation
        loader: () => import('./models/SimpleBlockModel'),
      },
    });
  }
}

export default PluginSimpleBlockClient;

registerModelLoaders utilise l'import dynamique : le code du modèle ne se charge qu'à la première utilisation effective — c'est la méthode d'enregistrement recommandée.

Étape 5 : activer le plugin

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

Une fois activé, créez une nouvelle page, cliquez sur « Ajouter un bloc » et vous verrez « Simple block ». Après ajout, cliquez sur le bouton de configuration du bloc pour éditer le contenu HTML.

Code source complet

Récapitulatif

Capacités utilisées dans cet exemple :

CapacitéUtilisationDocumentation
Rendu du blocBlockModel + renderComponent()FlowEngine → Extension de bloc
Inscription au menudefine({ label })Aperçu de FlowEngine
Panneau de configurationregisterFlow() + uiSchemaAperçu de FlowEngine
Enregistrement de modèleregisterModelLoaders (chargement à la demande)Plugin
Traduction différéetExpr()Internationalisation i18n

Liens connexes