Mohamed NufaijSept. 3, 2025
Odoo’s frontend has changed a lot with the introduction of Owl (Odoo Web Library)—a lightweight JavaScript framework designed for building reactive and modular interfaces. In Odoo 18, Owl has been refined further, and one of its most useful features is Hooks.
Hooks allow developers to manage component state, lifecycle, and logic in a clean and reusable way. Instead of repeating code, you can use hooks to handle common tasks like focusing inputs, managing events, pagination, or positioning elements.
In this blog, we’ll break down the main Owl hooks in Odoo 18, how they work, and how you can use them in real projects.
The useAssets hook helps load assets like scripts and styles only when needed. This makes your module faster and avoids unnecessary loading.
Location: @web/core/assets
Use case: Lazy-loading CSS or JS when a component is rendered.
If you’ve ever wanted an input field to be automatically focused, useAutofocus makes it simple. It applies focus to an element marked with t-ref="autofocus" as soon as it appears.
Location: @web/core/utils/hooks
Example:
import { useAutofocus } from "@web/core/utils/hooks";
class Comp {
setup() {
this.inputRef = useAutofocus();
}
static template = "Comp";
}
<t t-name="Comp">
<input t-ref="autofocus" type="text"/>
</t>
useBus connects your component to an event bus. It automatically removes listeners when the component is destroyed, preventing memory leaks.
Location: @web/core/utils/hooks
Example:
import { useBus } from "@web/core/utils/hooks";
class MyComponent {
setup() {
useBus(this.env.bus, "some-event", event => {
console.log("Event received:", event);
});
}
}
This is perfect for real-time updates like notifications or dynamic refreshes.
Pagination is common in Odoo views. The usePager hook makes it easy to add a pager to your custom views.
Location: @web/search/pager_hook
Example:
import { usePager } from "@web/search/pager_hook";
class CustomView {
setup() {
const state = owl.hooks.useState({
offset: 0,
limit: 80,
total: 50,
});
usePager(() => {
return {
offset: this.state.offset,
limit: this.state.limit,
total: this.state.total,
onUpdate: (newState) => {
Object.assign(this.state, newState);
},
};
});
}
}
When creating dropdowns, tooltips, or popovers, positioning is critical. usePosition aligns an element (the popper) relative to a reference element and keeps it updated on resize/scroll.
Location: @web/core/position_hook
Example:
import { usePosition } from "@web/core/position_hook";
import { Component, xml } from "@odoo/owl";
class MyPopover extends Component {
static template = xml`
<div t-ref="popper">
I am positioned through a wonderful hook!
</div>
`;
setup() {
// Here, the reference is the target props, which is an HTMLElement
usePosition(this.props.target);
}
}
For content editing, useSpellCheck enables or disables browser spell checking dynamically on inputs or contenteditable elements.
Location: @web/core/utils/hooks
Example:
import { useSpellCheck } from "@web/core/utils/hooks";
class Comp {
setup() {
this.simpleRef = useSpellCheck();
this.customRef = useSpellCheck({ refName: "custom" });
}
static template = "Comp";
}
<t t-name="Comp">
<input t-ref="spellcheck" type="text"/>
<textarea t-ref="custom"/>
</t>
Owl hooks are not just “nice to have”—they:
For Odoo developers, mastering these hooks means building faster, cleaner, and more interactive modules.
Odoo 18’s Owl hooks—like useAutofocus, useBus, usePager, usePosition, and useSpellCheck—give you powerful tools to handle common UI needs with minimal effort. By adopting them, you can write less repetitive code and build more modular components.
Which Owl hook have you used most in your Odoo projects? Share your experience in the comments below!
Hooks are reusable functions in Owl that let you manage state, events, and lifecycle logic inside Odoo components.
Unlike manual listeners, useBus automatically removes itself when the component unmounts, preventing memory leaks.
Yes, you can combine different hooks like usePager and usePosition in the same component.
Yes, they simplify lifecycle management by letting you handle tasks like setup, cleanup, and state updates with minimal code.
They are mostly available under @web/core/utils/hooks, @web/search/pager_hook, and @web/core/position_hook.
0