Tạo một Field component tùy chỉnh

Trong NocoBase, Field component được dùng để hiển thị và chỉnh sửa dữ liệu trong table và form. Ví dụ này hướng dẫn cách dùng ClickableFieldModel để tạo một component hiển thị Field tùy chỉnh — bọc giá trị field bằng dấu ngoặc vuông [], và gắn vào field interface kiểu input.

Đọc trước

Nên tìm hiểu các nội dung sau trước khi phát triển để mượt mà hơn:

Kết quả cuối cùng

Chúng ta sẽ tạo một component hiển thị Field tùy chỉnh:

  • Kế thừa ClickableFieldModel, tự định nghĩa logic render
  • Bọc giá trị field bằng [] khi hiển thị
  • Gắn vào field kiểu input (single-line text) qua bindModelToInterface

Sau khi bật plugin, tìm một cột field single-line text trong block table, click vào nút cấu hình của cột, và trong dropdown "Field component" bạn sẽ thấy lựa chọn DisplaySimpleFieldModel. Sau khi chuyển sang, giá trị của cột sẽ được hiển thị theo định dạng [value].

Toàn bộ source code xem tại @nocobase-example/plugin-field-simple. Nếu bạn muốn chạy thử trực tiếp ở local:

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

Sau đây ta sẽ xây dựng plugin này từ đầu, từng bước một.

Bước 1: Tạo khung plugin

Tại thư mục gốc của repo, chạy:

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

Chi tiết xem tại Viết Plugin đầu tiên.

Bước 2: Tạo Field Model

Tạo file mới src/client-v2/models/DisplaySimpleFieldModel.tsx. Đây là phần lõi của plugin — định nghĩa cách field render và gắn vào loại field interface nào.

// src/client-v2/models/DisplaySimpleFieldModel.tsx
import React from 'react';
import { ClickableFieldModel } from '@nocobase/client-v2';
import { DisplayItemModel } from '@nocobase/flow-engine';
import { tExpr } from '../locale';

export class DisplaySimpleFieldModel extends ClickableFieldModel {
  public renderComponent(value: string) {
    // this.context.record có thể lấy bản ghi đầy đủ của hàng hiện tại
    console.log('Bản ghi hiện tại:', this.context.record);
    console.log('Index của bản ghi hiện tại:', this.context.recordIndex);
    return <span>[{value}]</span>;
  }
}

// Đặt tên hiển thị trong dropdown "Field component"
DisplaySimpleFieldModel.define({
  label: tExpr('Simple field'),
});

// Gắn vào field interface kiểu 'input' (single-line text)
DisplayItemModel.bindModelToInterface('DisplaySimpleFieldModel', ['input']);

Một số điểm chính:

  • renderComponent(value) — Nhận giá trị field hiện tại làm tham số, trả về JSX để render
  • this.context.record — Lấy bản ghi dữ liệu đầy đủ của hàng hiện tại
  • this.context.recordIndex — Lấy index của hàng hiện tại
  • ClickableFieldModel — Kế thừa từ FieldModel, có khả năng tương tác click
  • define({ label }) — Đặt tên hiển thị trong dropdown "Field component", nếu không thêm thì sẽ hiển thị trực tiếp tên class
  • DisplayItemModel.bindModelToInterface() — Gắn Field model vào loại field interface chỉ định (ví dụ input đại diện cho field single-line text), nhờ đó field tương ứng có thể chọn component hiển thị này

Bước 3: Thêm file đa ngôn ngữ

Chỉnh sửa file dịch trong src/locale/ của plugin, thêm bản dịch cho các key được dùng bởi tExpr():

// src/locale/zh-CN.json
{
  "Simple field": "简单字段"
}
// src/locale/en-US.json
{
  "Simple field": "Simple field"
}
Lưu ý

Khi thêm file ngôn ngữ lần đầu, bạn cần khởi động lại ứng dụng để có hiệu lực.

Về cách viết file dịch và các cách dùng khác của tExpr(), xem chi tiết tại i18n.

Bước 4: Đăng ký trong Plugin

Chỉnh sửa src/client-v2/plugin.tsx, dùng registerModelLoaders để load model theo nhu cầu:

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

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

export default PluginFieldSimpleClient;

Bước 5: Bật plugin

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

Sau khi bật, tìm một cột field single-line text trong block table, click vào nút cấu hình của cột, trong dropdown "Field component" bạn có thể chuyển sang component hiển thị tùy chỉnh này.

Source code đầy đủ

Tóm tắt

Các khả năng được sử dụng trong ví dụ này:

Khả năngCách dùngTài liệu
Render FieldClickableFieldModel + renderComponent(value)FlowEngine → Mở rộng Field
Gắn field interfaceDisplayItemModel.bindModelToInterface()FlowEngine → Mở rộng Field
Đăng ký Modelthis.flowEngine.registerModelLoaders()Plugin

Liên kết liên quan