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:

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:

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óComponentriê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 quacommandId. Tách lệnh khỏi nơi hiển thị để một lệnh dùng ở nhiều chỗ.isAvailabletrê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_editorPlugin), 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ề
- 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_editorkhai các resource mà editor tự gom. user_commandskhai 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ị (quacommandId) để một lệnh dùng nhiều chỗ. Đăng ký vào registrywebsite-plugins.- Đây là API Odoo 19 (
html_editorPlugin) — chính các plugin lõi (nhưstar_plugin) dùng đúng cấu trúc này. Nạp trongwebsite.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.