Bài trước thêm tùy chọn cho một snippet. Nhưng đôi khi bạn muốn mở rộng chính trình biên tập — thêm một lệnh vào powerbox (cái menu bật lên khi gõ /), một nút vào thanh công cụ chọn văn bản, hay một mục vào menu. Odoo 19 làm tất cả qua cùng một cơ chế: một Plugin của html_editor, khai các "resource" mà editor gom lại.

Plugin editor: khai resource, editor tự gom

Trình biên tập Odoo 19 (html_editor) không hard-code danh sách lệnh. Nó gom các resource từ mọi plugin đăng ký: user_commands (các lệnh), powerbox_items (mục trong menu /), toolbar_items (nút trên thanh công cụ), powerbox_categories... Bạn viết một Plugin khai resource, đăng ký, xong.

Mình viết một plugin thêm lệnh "Lời chào quán" vào powerbox — gõ /, chọn nó, một khối chào cà phê được chèn:

Ảnh chụp đoạn mã Odoo 19 nền tối file loi_chao_plugin js, import Plugin từ html_editor plugin và parseHTML từ html_editor utils html, lớp LoiChaoPlugin kế thừa Plugin có static id loiChaoQuan và static dependencies dom history, thuộc tính resources gồm user_commands khai một lệnh id chenLoiChao title Lời chào quán icon fa-coffee run gọi this chenLoiChao bind this, và powerbox_items đưa lệnh vào menu gõ dấu gạch chéo với categoryId widget commandId chenLoiChao trỏ tới lệnh trên title Lời chào quán icon fa-coffee keywords cà phê chào. Method chenLoiChao dựng chuỗi HTML lời chào rồi gọi this dependencies dom insert parseHTML để chèn tại con trỏ và this dependencies history addStep. Cuối cùng registry category website-plugins add plugin

Hình 1: Plugin thêm một lệnh vào editor. user_commands khai lệnh (id, title, icon, run). powerbox_items đưa lệnh đó vào menu / (tham chiếu qua commandId, thêm keywords để tìm). Hàm run chèn HTML tại con trỏ bằng this.dependencies.dom.insert(parseHTML(...)) rồi history.addStep() (để hoàn tác được). Đăng ký vào registry website-plugins. Code này nạp thật trong website.assets_editor, module nâng cấp không một lỗi.

Đây đúng là cách lõi làm

Không phải mình bịa cấu trúc này — đó chính là API mà các plugin lõi của Odoo 19 dùng. Ví dụ tính năng "chèn xếp hạng sao" của editor:

Ảnh chụp trích đoạn thật từ file lõi html_editor star_plugin js, thuộc tính resources có user_commands khai lệnh id addStars title Stars description Insert a rating icon fa-star run this addStars bind this isAvailable isHtmlContentSupported, và powerbox_items gồm hai mục 3 Stars và 5 Stars mỗi mục có title description categoryId widget commandId addStars và commandParams length 3 hoặc 5, cùng selectors_for_feff_providers trả về chấm o_stars. Tiêu đề ghi file lõi thật cùng API user_commands và powerbox_items

Hình 2: Trích thật từ html_editor/.../star_plugin.js của Odoo 19. Cùng một resources với user_commands và powerbox_items mà plugin của mình dùng — chỉ khác nội dung. Một lệnh addStars được hai mục powerbox ("3 Stars", "5 Stars") gọi lại với commandParams khác nhau. Đây là bằng chứng cấu trúc mình trình bày là API chính thức, không phải suy diễn.

Powerbox, toolbar, và các điểm mở rộng

Cùng cơ chế Plugin, bạn chạm được nhiều nơi trong editor:

  • powerbox_items — mục trong menu gõ / (như trên). Hợp cho chèn một khối/thành phần.
  • toolbar_items — nút trên thanh công cụ hiện khi bôi đen văn bản (in đậm, căn lề... là các mục này). Có Component riêng nếu cần dropdown.
  • user_commands — định nghĩa lệnh dùng chung, được powerbox/toolbar/phím tắt gọi lại qua commandId. Tách lệnh khỏi nơi hiển thị để một lệnh dùng ở nhiều chỗ.
  • isAvailable trên lệnh quyết định khi nào lệnh khả dụng (ví dụ chỉ khi con trỏ trong vùng cho phép).

Vài lưu ý

  • Plugin editor nạp trong website.assets_editor (bundle của trình biên tập website) — không phải frontend, vì chỉ cần khi biên tập.
  • Đây là API Odoo 19 mới (html_editor Plugin), khác hẳn hệ Wysiwyg/we-* cũ. Tài liệu/blog cũ không áp được.
  • history.addStep() sau khi đổi DOM để thao tác hoàn tác được — quên là người dùng không Ctrl+Z lại được.

Ba ý mang về

  1. Bạn mở rộng được chính trình biên tập website, không chỉ một snippet — thêm lệnh vào powerbox, nút vào thanh công cụ — qua một Plugin của html_editor khai các resource mà editor tự gom.
  2. user_commands khai lệnh (id, run); powerbox_items đưa lệnh vào menu /; toolbar_items đưa vào thanh công cụ. Tách lệnh khỏi nơi hiển thị (qua commandId) để một lệnh dùng nhiều chỗ. Đăng ký vào registry website-plugins.
  3. Đây là API Odoo 19 (html_editor Plugin) — chính các plugin lõi (như star_plugin) dùng đúng cấu trúc này. Nạp trong website.assets_editor, và nhớ history.addStep() để thao tác hoàn tác được.

Xong mảng website và editor, ta quay lại backend với một chi tiết nhỏ mà hữu dụng: phần sau viết một widget nhỏ trong thẻ Kanban bằng JS — thêm một mảnh tương tác vào từng thẻ trên bảng kanban.