Odoo 19's web interface structure uses the OWL library's (Odoo Web Library) features. OWL hooks provide an efficient way to manage state across UI components and reuse code. OWL's Observer pattern's reactive design enables dynamic UI updates in response to state changes.
This manual examines the creation of a customized Hook with features specifically designed for Odoo 19. This guide provides key technical techniques for enhancing interface behavior or customizing it to particular workflows.
Let's investigate how to make unique hooks for Odoo 19.
Developing the Hook
Initially, we will write the code for the custom hook:
pointer_tracker.js
/** @odoo-module **/
import { useState, onWillDestroy } from "@odoo/owl";
export function cursorTracker() {
const coordinates = useState({ x: 0, y: 0 });
function refreshPosition(e) {
coordinates.x = e.clientX;
coordinates.y = e.clientY;
}
window.addEventListener("mousemove", refreshPosition);
onWillDestroy(() => {
window.removeEventListener("mousemove", refreshPosition);
});
return coordinates;
}
We're using current OWL functions along with our own logic. The code creates a position tracker that updates with cursor movements and removes event listeners when components are unmounted.
Directory Structure for Odoo 19 Modules
The execution needs this specific directory structure:
cursor_utility/
+-- __init__.py
+-- __manifest__.py
+-- static/
+-- src/
+-- js/
+-- pointer_tracker.js
After you build and register this utility module, installing it in the database will make the custom hook available across the system.
Implementing the Hook
We will now show how to practically use our custom hook.
We have created a cursor position tracker, and we plan to show the coordinates in the system menu. We need to develop components that use our custom hook.
Implementing in the System Menu
CursorDisplay.xml
<?xml version="1.0" encoding="UTF-8" ?>
<templates>
<t t-name="cursor_display.PositionIndicator" owl="1">
<div class="d-flex align-items-center m-2">
<div class="text-white m-2">Cursor: <t t-esc="pointerPosition.x"/>, <t t-esc="pointerPosition.y"/></div>
</div>
</t>
</templates>
This shows a visual component that displays the cursor's coordinates. Odoo 19 needs naming rules for templates that start with module names.
CursorDisplay.js
/** @odoo-module **/
import { registry } from "@web/core/registry";
import { cursorTracker } from "@cursor_utility/js/pointer_tracker";
import { Component } from "@odoo/owl";
class PositionIndicator extends Component {
static template = "cursor_display.PositionIndicator";
setup() {
this.pointerPosition = cursorTracker();
}
}
export const menuPositionItem = {
Component: PositionIndicator,
sequence: 25,
};
registry.category('systray').add('cursor_position', menuPositionItem);
Module Structure for the Implementation
cursor_display/
+-- __init__.py
+-- __manifest__.py
+-- static/
+-- src/
|-js/
| +-- cursor_display.js
|
|-xml/
+-- cursor_display.xml
By installing both modules, the system menu can show the cursor position in real-time. This uses our custom hook.

In the screenshot above, we can see where the cursor is placed.
Conclusion
Custom hooks in Odoo 19 offer powerful functions for improving interface features based on specific needs. The OWL framework in Odoo 19 has better import consistency, improved resource organization, and optimized performance. Hooks make it easy to customize and expand Odoo interfaces. This allows for tailored experiences. They provide the flexibility to improve Odoo 19's capabilities, whether by enhancing existing processes or creating new features.
To read more about How to Create Custom Hooks in Odoo 18 OWL, refer to our blog How to Create Custom Hooks in Odoo 18 OWL.