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 -->

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:

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.
monetarycần field Monetary +currency_id;imagecần Image/Binary;handlecầ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ị.
prioritycho bấm sao thay vì chọn số;boolean_togglegạt công tắc thay vì tick;email/phonebiế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 (
handlechỉ ý nghĩa trong list;imagelớ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.
progressbarhiể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ìnhmax_valuequa options.- Widget có
options="{...}"để tinh chỉnh (ví dụmany2many_tagsvớ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ề
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.- Chọn widget khớp kiểu field và đúng chức năng:
monetarycần Monetary+currency,prioritycho bấm sao,boolean_togglecho công tắc,email/phone/urlcho link bấm được — widget cải thiện cả nhập liệu. badgeghépdecoration-*cho nhãn đổi màu theo trạng thái;progressbarhiểu giá trị là %; tinh chỉnh thêm quaoptions. Ư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.