FlowEngine

Di NocoBase, FlowEngine adalah engine inti yang menggerakkan konfigurasi visual. Block, Field, tombol Action di antarmuka NocoBase semuanya dikelola melalui FlowEngine — termasuk rendering, panel konfigurasi, dan persistensi konfigurasinya.

20260403215904

Bagi developer plugin, FlowEngine menyediakan dua konsep inti:

  • FlowModel — Model Component yang dapat dikonfigurasi, bertanggung jawab merender UI dan mengelola props
  • Flow — Alur konfigurasi, mendefinisikan panel konfigurasi Component dan logika pemrosesan data

Jika Component Anda perlu muncul di menu "Tambah Block / Field / Action", atau perlu mendukung pengguna melakukan konfigurasi visual di antarmuka, perlu dibungkus dengan FlowModel. Jika tidak memerlukan kapabilitas ini, Component React biasa sudah cukup — lihat Component vs FlowModel.

Apa itu FlowModel

Berbeda dengan Component React biasa, FlowModel selain bertanggung jawab merender UI, juga mengelola sumber props, definisi panel konfigurasi, dan persistensi konfigurasi. Sederhananya: props Component biasa di-hardcode, props FlowModel di-generate dinamis melalui Flow.

Untuk memahami arsitektur menyeluruh FlowEngine secara mendalam, dapat melihat Dokumentasi Lengkap FlowEngine. Berikut diperkenalkan dari sudut pandang developer plugin, cara menggunakannya.

Contoh Minimal

Sebuah FlowModel dari pembuatan hingga registrasi, dibagi menjadi tiga langkah:

1. Extends Class Dasar, Implementasikan renderComponent

// models/HelloBlockModel.tsx
import React from 'react';
import { BlockModel } from '@nocobase/client-v2';
import { tExpr } from '@nocobase/flow-engine';

export class HelloBlockModel extends BlockModel {
  renderComponent() {
    return (
      <div>
        <h3>Hello FlowEngine!</h3>
        <p>Ini adalah Block kustom.</p>
      </div>
    );
  }
}

// define() mengatur nama tampilan di menu
HelloBlockModel.define({
  label: tExpr('Hello block'),
});

renderComponent() adalah method rendering model ini, mirip dengan render() Component React. tExpr() digunakan untuk terjemahan tertunda — karena define() dieksekusi saat module dimuat, pada saat ini i18n belum diinisialisasi. Untuk detail lihat Kapabilitas Umum Context → tExpr.

2. Daftarkan di Plugin

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

export class MyPlugin extends Plugin {
  async load() {
    this.flowEngine.registerModelLoaders({
      HelloBlockModel: {
        // Loading sesuai kebutuhan, modul dimuat saat pertama kali digunakan
        loader: () => import('./models/HelloBlockModel'),
      },
    });
  }
}

3. Gunakan di Antarmuka

Setelah registrasi selesai, melalui pengaktifan plugin (untuk pengaktifan plugin dapat merujuk ke Ikhtisar Plugin Development), buat halaman baru di antarmuka NocoBase, klik "Tambah Block" akan terlihat "Hello block" Anda.

20260403221815

Menambahkan Item Konfigurasi dengan registerFlow

Hanya bisa rendering tidak cukup — nilai inti FlowModel adalah dapat dikonfigurasi. Melalui registerFlow() Anda dapat menambahkan panel konfigurasi ke model, memungkinkan pengguna memodifikasi property di antarmuka.

Contoh Block yang mendukung edit konten HTML:

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

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

SimpleBlockModel.define({
  label: tExpr('Simple block'),
});

SimpleBlockModel.registerFlow({
  key: 'flow1',
  title: tExpr('Simple Block Flow'),
  on: 'beforeRender', // Eksekusi sebelum render
  steps: {
    editHtml: {
      title: tExpr('Edit HTML Content'),
      // uiSchema mendefinisikan UI panel konfigurasi
      uiSchema: {
        html: {
          type: 'string',
          title: tExpr('HTML Content'),
          'x-decorator': 'FormItem',
          'x-component': 'Input.TextArea',
        },
      },
      // Nilai default
      defaultParams: {
        html: `<h3>This is a simple block</h3>
<p>You can edit the HTML content.</p>`,
      },
      // Di handler set nilai panel konfigurasi ke props model
      handler(ctx, params) {
        ctx.model.props.html = params.html;
      },
    },
  },
});

Beberapa poin kunci:

  • on: 'beforeRender' — Berarti Flow ini dieksekusi sebelum rendering, nilai panel konfigurasi akan ditulis ke this.props sebelum rendering
  • uiSchema — Menggunakan format JSON Schema untuk mendefinisikan UI panel konfigurasi, sintaks referensi UI Schema
  • handler(ctx, params)params adalah nilai yang diisi pengguna di panel konfigurasi, diset ke model melalui ctx.model.props
  • defaultParams — Nilai default panel konfigurasi

Cara Penulisan uiSchema Umum

uiSchema berbasis JSON Schema, v2 kompatibel dengan sintaks uiSchema, namun skenario penggunaan terbatas — terutama digunakan di panel konfigurasi Flow untuk mendeskripsikan UI form. Sebagian besar rendering Component runtime direkomendasikan menggunakan Component Antd langsung, tidak perlu menggunakan uiSchema.

Berikut tercantum beberapa Component yang paling sering digunakan (referensi lengkap lihat UI Schema):

uiSchema: {
  // Input teks
  title: {
    type: 'string',
    title: 'Judul',
    'x-decorator': 'FormItem',
    'x-component': 'Input',
  },
  // Teks multi-baris
  content: {
    type: 'string',
    title: 'Konten',
    'x-decorator': 'FormItem',
    'x-component': 'Input.TextArea',
  },
  // Dropdown selection
  type: {
    type: 'string',
    title: 'Tipe',
    'x-decorator': 'FormItem',
    'x-component': 'Select',
    enum: [
      { label: 'Utama', value: 'primary' },
      { label: 'Default', value: 'default' },
      { label: 'Dashed', value: 'dashed' },
    ],
  },
  // Switch
  bordered: {
    type: 'boolean',
    title: 'Tampilkan Border',
    'x-decorator': 'FormItem',
    'x-component': 'Switch',
  },
}

Setiap field dibungkus dengan 'x-decorator': 'FormItem', sehingga akan otomatis dilengkapi judul dan layout.

Penjelasan Parameter define()

FlowModel.define() digunakan untuk mengatur metadata model, mengontrol cara tampilannya di menu. Yang paling sering digunakan dalam pengembangan plugin adalah label, namun masih mendukung lebih banyak parameter:

ParameterTipePenjelasan
labelstring | ReactNodeNama tampilan di menu "Tambah Block / Field / Action", mendukung terjemahan tertunda tExpr()
iconReactNodeIcon di menu
sortnumberBobot sorting, semakin kecil semakin di depan. Default 0
hideboolean | (ctx) => booleanApakah disembunyikan di menu, mendukung penilaian dinamis
groupstringIdentifier grup, untuk dikelompokkan ke grup menu tertentu
childrenSubModelItem[] | (ctx) => SubModelItem[]Item submenu, mendukung function asinkron untuk konstruksi dinamis
toggleableboolean | (model) => booleanApakah mendukung perilaku toggle (unik di bawah parent yang sama)
searchablebooleanApakah submenu mengaktifkan pencarian

Sebagian besar plugin hanya perlu mengatur label:

MyBlockModel.define({
  label: tExpr('My block'),
});

Jika perlu mengontrol sorting atau menyembunyikan, dapat menambahkan sort dan hide:

MyBlockModel.define({
  label: tExpr('My block'),
  sort: 10,       // Diletakkan di belakang
  hide: (ctx) => !ctx.someCondition,  // Sembunyikan kondisi
});

Pemilihan Class Dasar FlowModel

NocoBase menyediakan beberapa class dasar FlowModel, pilih berdasarkan tipe yang ingin Anda perluas:

Class DasarTujuanDokumentasi Detail
BlockModelBlock biasaEkstensi Block
DataBlockModelBlock yang perlu mengambil data sendiriEkstensi Block
CollectionBlockModelMengikat tabel data, otomatis mengambil dataEkstensi Block
TableBlockModelBlock tabel lengkap, dengan kolom field, action bar, dll.Ekstensi Block
FieldModelComponent fieldEkstensi Field
ActionModelTombol ActionEkstensi Action

Biasanya, untuk membuat Block tabel gunakan TableBlockModel (paling sering digunakan, siap pakai), perlu rendering yang sepenuhnya kustom gunakan CollectionBlockModel atau BlockModel, untuk Field gunakan FieldModel, untuk tombol Action gunakan ActionModel.

Tautan Terkait