Một field trang_thai kiểu Selection có thể hiện thành một ô thả xuống bình thường, hoặc thành một badge màu bắt mắt. Một field diem kiểu số có thể là con số trơ, hoặc một thanh tiến độ. Cùng dữ liệu, cùng field — khác nhau ở một chữ: widget. Chọn đúng widget là cách rẻ nhất để form vừa đẹp vừa dễ dùng. Bài này gắn nhiều widget lên một form và xem chúng chạy thật.

widget đổi cách hiển thị, không đổi dữ liệu

Thêm widget="..." vào thẻ field để chọn cách render và nhập liệu. Dữ liệu bên dưới không đổi — chỉ giao diện đổi:

<field name="anh_the" widget="image" class="oe_avatar"/>   <!-- ảnh -->

<field name="trang_thai" widget="badge"          <!-- nhãn bo tròn có màu -->
       decoration-success="trang_thai == 'dang_dung'"
       decoration-danger="trang_thai == 'khoa'"/>

<field name="diem" widget="progressbar"/>   <!-- thanh tiến độ -->
<field name="so_du" widget="monetary"/>      <!-- tiền + đơn vị -->
<field name="uu_dai_ids" widget="many2many_tags"/> <!-- thẻ tag -->

Ảnh chụp mã XML nền tối minh hoạ nhiều widget trên field, field anh_the widget image class oe_avatar hiển thị ảnh, field trang_thai widget badge kèm decoration-success khi đang dùng và decoration-danger khi khoá thành nhãn bo tròn màu, field diem widget progressbar thành thanh tiến độ, field so_du widget monetary thành tiền có đơn vị, field uu_dai_ids widget many2many_tags thành thẻ tag, phần cuối liệt kê các widget hay dùng khác như priority sao xếp hạng boolean_toggle công tắc handle kéo sắp xếp email phone url link bấm được selection_badge percentage html pdf_viewer

Hình 1: Mỗi field một widget. widget quyết định cách field hiện ra và cho nhập; dữ liệu trong database không đổi. Badge còn nhận decoration-* để đổi màu theo điều kiện — giống list nhưng áp cho chính badge đó.

Xem thật: một form, nhiều widget

Gắn các widget trên lên form thẻ Vàng và mở nó ra:

Ảnh chụp form Odoo thẻ VIP-0003 hạng Vàng với nhiều widget, góc phải trên là ảnh thẻ hình vuông màu tím có chữ VIP hiển thị bằng widget image, trường Trạng thái hiện nhãn bo tròn màu xanh lá ghi Đang dùng bằng widget badge, trường Điểm tích luỹ hiện một thanh tiến độ kèm số 150 phần trăm bằng widget progressbar, trường Số dư hiện 0 đô la bằng widget monetary, trường Khách hàng nhãn đỏ vì bắt buộc

Hình 2: Cùng form, nhiều widget cùng chạy thật. image: ảnh thẻ hình vuông (góc phải, class oe_avatar). badge: "Đang dùng" thành nhãn bo tròn xanh (nhờ decoration-success). progressbar: "Điểm tích luỹ" thành thanh tiến độ hiện 150%. monetary: "Số dư" hiện kèm đơn vị tiền. Không widget nào cần code — chỉ khai trong XML.

Bảng widget hay dùng

widget Dùng cho field Hiển thị
badge Selection/Char Nhãn bo tròn có màu
progressbar Integer/Float Thanh tiến độ %
monetary Monetary Số tiền + đơn vị (cần currency_id)
image Image/Binary Ảnh (thêm oe_avatar cho khung vuông)
many2many_tags Many2many Các thẻ bo tròn
priority Selection Dãy sao xếp hạng bấm được
boolean_toggle Boolean Công tắc gạt
handle Integer (sequence) Tay kéo sắp xếp thứ tự
email / phone / url Char Link bấm được (mở mail/gọi/mở web)
selection_badge Selection Các nút chọn dạng badge
html Html Trình soạn thảo rich text

Chọn widget cho đúng, không chỉ cho đẹp

  • Widget phải khớp kiểu field. monetary cần field Monetary + currency_id; image cần Image/Binary; handle cần một field số dùng làm thứ tự. Gán lệch kiểu là lỗi hoặc hiển thị sai.
  • Widget cải thiện cả nhập liệu, không chỉ hiển thị. priority cho bấm sao thay vì chọn số; boolean_toggle gạt công tắc thay vì tick; email/phone biến text thành link bấm được — trải nghiệm khác hẳn.
  • badge + decoration-* cho nhãn đổi màu theo trạng thái — rất hợp cho field trạng thái.
  • Widget dùng được ở cả list lẫn form (và kanban) — nhưng một số chỉ hợp một nơi (handle chỉ ý nghĩa trong list; image lớn hợp form).

Vài lưu ý Odoo 19

  • Không lạm dụng widget lạ. Odoo có hàng chục widget; chọn cái đúng chức năng trước, đẹp sau. Một Selection bình thường nhiều khi rõ hơn một badge rối màu.
  • progressbar hiểu giá trị là phần trăm (150 điểm hiện "150%"); nếu muốn thang khác, cần cấu hình max_value qua options.
  • Widget có options="{...}" để tinh chỉnh (ví dụ many2many_tags với {'color_field': 'color'} để tag có màu).
  • Widget tuỳ biến (custom) viết bằng OWL/JavaScript — nhưng phần lớn nhu cầu đã có widget sẵn, đừng vội tự viết.

Ba ý mang về

  1. widget="..." đổi cách một field hiển thị và cho nhập, không đổi dữ liệu bên dưới. Đã chứng minh: cùng form có image (ảnh), badge (nhãn xanh "Đang dùng"), progressbar (150%), monetary (tiền) — chỉ khai XML.
  2. Chọn widget khớp kiểu field và đúng chức năng: monetary cần Monetary+currency, priority cho bấm sao, boolean_toggle cho công tắc, email/phone/url cho link bấm được — widget cải thiện cả nhập liệu.
  3. badge ghép decoration-* cho nhãn đổi màu theo trạng thái; progressbar hiểu giá trị là %; tinh chỉnh thêm qua options. Ưu tiên widget có sẵn trước khi viết widget tuỳ biến.

Ta đã tô, sắp, và chọn cách hiển thị field. Lần sau chuyển sang hành động: Phần sau mổ xẻ nút bấm trên view — type="object" gọi method Python và type="action" mở một action, để form không chỉ hiển thị mà còn làm việc.