Component đã hiển thị danh sách thẻ. Giờ cần nó phản ứng: người dùng bấm một thẻ, thẻ đó được chọn và tô sáng. Trong OWL, bạn gắn sự kiện bằng chỉ thị t-on — t-on-click, t-on-input, t-on-submit... Nghe quen như HTML, nhưng có một chỗ khác khiến người mới vấp: khi lặp danh sách, làm sao handler biết thẻ nào vừa được bấm?
Gọi thẳng, hay truyền tham số
Có hai cách viết t-on-click, và chọn đúng phụ thuộc bạn có cần truyền tham số hay không:

Hình 1: Gọi thẳng t-on-click="chonThe" — OWL truyền vào handler một tham số duy nhất: ev (đối tượng sự kiện DOM). Truyền tham số thì bọc trong arrow function: t-on-click="(ev) => this.chonThe(card, ev)" — nhờ đó handler biết chính xác card nào. Và OWL không có modifier .stop/.prevent như Vue: muốn chặn thì gọi ev.stopPropagation() / ev.preventDefault() bằng tay trong handler.
Đo: bấm là chọn, và tô sáng
Trước khi bấm, không có thẻ nào được chọn:

Hình 2: Trạng thái ban đầu — state.chon là null, nên không thẻ nào được tô và dòng dưới ghi "Chưa chọn thẻ nào".
Bấm vào thẻ VIP-0003, handler chonThe(card) chạy với đúng card của thẻ đó:

Hình 3: Sau khi bấm — thẻ VIP-0003 có viền tím dày (nhờ t-att-class so state.chon.id === card.id), và dòng dưới đổi thành "Đang chọn: VIP-0003 (150 điểm)". Handler nhận đúng card của thẻ được bấm nhờ arrow function, gán vào state.chon, và vì chon nằm trong useState nên giao diện tự vẽ lại. Toàn bộ vòng: sự kiện → handler → đổi state → render. Chụp bằng trình duyệt thật, không lỗi Console.
Vài lưu ý về sự kiện trong OWL
- Gọi thẳng khi không cần tham số (
t-on-click="luu"), arrow khi cần (t-on-click="() => this.xoa(card)"). Đừng viếtt-on-click="this.xoa(card)"— nó gọi ngay lúc render, không phải khi bấm. - Không có
.stop/.prevent/.self. Đây là khác biệt lớn với Vue: chặn lan truyền hay hành vi mặc định phải gọi phương thức trênevtrong handler. - Handler luôn nhận
evcuối cùng khi gọi thẳng; với arrow, bạn tự quyết truyền gì.ev.targetlà element bị bấm,ev.currentTargetlà element gắnt-on. - Sự kiện + state = tương tác. Handler nên đổi state (
this.state.x = ...) để UI phản ứng, không nên thao tác DOM trực tiếp — để OWL lo phần vẽ.
Ba ý mang về
t-on-click="method"gọi thẳng (handler nhậnev);t-on-click="() => this.method(arg)"dùng arrow để truyền tham số — cần thiết khi lặpt-foreachđể biết item nào.- OWL không có modifier
.stop/.preventnhư Vue — gọiev.stopPropagation()/ev.preventDefault()bằng tay trong handler. - Vòng tương tác chuẩn: sự kiện → handler → đổi
state(tronguseState) → OWL tự render lại; handler đừng thao tác DOM trực tiếp.
Handler của ta gọi this.orm.searchRead để lấy dữ liệu — cái orm đó từ đâu ra? Nó là một service của Odoo. Phần sau đi vào useService — gọi dịch vụ Odoo từ component: orm, notification, action, dialog... và cách chúng nối component với phần còn lại của hệ thống.