Odoo 17 comes with a revamped web framework known as Owl (Odoo Web Library), which facilitates the creation of dynamic, efficient, and modular web components. This advanced framework utilizes modern JavaScript features to enable developers to build interactive and reusable components effortlessly within the Odoo platform.
Owl is a high-performance, lightweight framework tailored for developing reactive and component-based web applications. As the fundamental units of this framework, Owl components allow developers to easily build complex user interfaces. Their modular nature simplifies code maintenance and promotes reuse, making development more efficient and manageable.
Before diving into more complex applications, let's start by creating a simple Owl component in Odoo.
const { useState } = owl.hooks;
const { xml } = owl.tags;
class CounterComponent extends Component {
setup() {
this.state = useState({ count: 0 });
}
increment() {
this.state.count++;
}
}
CounterComponent.template = xml`
<div t-on-click="increment">
<span t-esc="state.count"/>
</div>`;
In this example, Owl is accessible as a global library within Odoo, allowing it to be used similarly to other Odoo libraries. Notice that the template is defined as a static property of the component, without using the static keyword.
Here's how the above component should be properly defined:
Javascript file:
/** @odoo-module **/
import { useState } from "@odoo/owl/hooks";
import { Component } from "@odoo/owl";
// Define the CounterComponent class
class CounterComponent extends Component {
setup() {
this.state = useState({ count: 0 });
}
increment() {
this.state.count++;
}
}
CounterComponent.template = 'myaddon.CounterComponent';
Xml file:
<?xml version="1.0" encoding="UTF-8"?>
<odoo>
<templates xml:space="preserve">
<t t-name="myaddon.CounterComponent">
<div t-on-click="increment">
<span t-esc="state.count"/>
</div>
</t>
</templates>
</odoo>
ActionSwiper
The ActionSwiper component triggers actions when an element is swiped horizontally. It wraps around a target element to enable swipe actions, which are executed when the user swipes past a certain portion of the element's width.
Location: @web/core/action_swiper/action_swiper
<ActionSwiper onLeftSwipe="Object" onRightSwipe="Object">
<SomeElement/>
</ActionSwiper>
To use this component, wrap it around your target element, as shown above. If you need to add swipe functionality to an existing element without duplicating its template, simply wrap it within ActionSwiper. You can also add props to control swapability, animations, and the minimum swipe distance required to trigger an action.
In this example, we use both onLeftSwipe and onRightSwipe props for the ActionSwiper component. Here are the props available for ActionSwiper:
animationOnMove: A boolean that determines whether the swipe has a translate effect.
animationType: An optional animation (e.g., bounce or forward) applied after the swipe is completed.
onLeftSwipe: Allows the ActionSwiper to be swiped to the left.
onRightSwipe: Allows the ActionSwiper to be swiped to the right.
swipeDistanceRatio: An optional minimum width ratio that must be swiped to trigger the action.
CheckBox
This component is a basic checkbox with an adjacent label. The checkbox and label are linked so that clicking the label toggles the checkbox.
Location: @web/core/checkbox/checkbox
The props available for the CheckBox component are:
value: A boolean indicating whether the checkbox is checked (true) or unchecked (false).
disabled: A boolean indicating whether the checkbox is disabled (true) or enabled (false).
ColorList
The ColorList component allows you to select a color from a predefined list. By default, it shows the currently selected color and remains collapsed unless the canToggle prop is provided. Various props can modify its behavior, enabling the list to always be expanded or making it act as a toggle that displays the available colors when clicked until a selection is made.
Location: @web/core/colorlist/colorlist
The available props for the ColorList component are as follows:
canToggle: A boolean indicating whether the color list can expand on click.
colors: An array containing the set of colors the component should display. Each color has a distinct ID.
forceExpanded: A boolean specifying whether the list is always expanded (true).
isExpanded: A boolean indicating whether the list is expanded by default (true).
onColorSelected: A function callback executed after selecting a color.
selectedColor: A number representing the ID of the selected color.
Dropdown
Dropdowns are robust components that offer various features to enhance user interaction. These features include:
* Toggling the item list upon clicking.
* Handling direct sibling dropdowns: when one is open, others toggle on hover.
* Closing on an outside click.
* Optional closure of the item list upon selecting an item.
* Execution of a function upon selecting an item.
* Support for sub dropdowns up to any level.
* Custom styling (SIY - Style It Yourself).
* Configurable hotkey for opening/closing or selecting a dropdown item.
* Keyboard navigation for accessibility (arrows, tab, shift+tab, home, end, enter, and escape).
* Automatic repositioning upon page scroll or resize.
* Smart determination of opening direction (right-to-left direction is automatically handled).
Location: @web/core/dropdown/dropdown and @web/core/dropdown/dropdown_item
To address these requirements efficiently, the Odoo framework provides two main components: the Dropdown component, responsible for the dropdown itself, and DropdownItem, representing each item in the dropdown list.
Xml file
<Dropdown>
<t t-set-slot="toggler">
<!-- Content in the "toggler" slot is rendered inside a button -->
Click me to toggle the dropdown menu!
</t>
<!-- Content in the "default" slot is rendered inside a div -->
<DropdownItem onSelected="selectItem1">Menu Item 1</DropdownItem>
<DropdownItem onSelected="selectItem2">Menu Item 2</DropdownItem>
</Dropdown>
The available props for the Dropdown component are:
startOpen: Defaults to false, setting this prop to true initializes the dropdown in an open state.
menuClass: Additional CSS class for styling the dropdown menu (e.g., <div class="dropdown-menu"/>).
togglerClass: Additional CSS class for styling the toggler (e.g., <button class="dropdown-toggle"/>).
hotkey: Enables the use of a keyboard hotkey to toggle the dropdown.
tooltip: Adds a tooltip to the toggler element.
beforeOpen: Hook executed just before opening the dropdown, allowing for pre-opening logic (potentially asynchronous).
manualOnly: If true (default is false), the dropdown toggles only when the button is clicked.
title: Content for the title attribute of the toggler element (default is none).
position: Specifies the desired position for the menu to open, using a valid useHook position (default is bottom-start).
toggler: When set to "parent", the <button class="dropdown-toggle"/> element is not rendered, and the toggling functionality is handled by the parent node (e.g., useful for pivot cells). (Default is undefined)
Notebook
The Notebook component is designed to showcase multiple pages within a tabbed interface. Tabs can be positioned either horizontally at the top or vertically on the left side of the element.
It has two options for defining Notebook pages: either by using slots or by passing dedicated props.
A page can be disabled using the isDisabled attribute, which can be set directly on the slot node or in the page declaration if the Notebook is used with pages provided as props. Once disabled, the corresponding tab appears grayed out and inactive.
Location: @web/core/notebook/notebook
The available props for the Notebook component are:
anchors: (Type: object) Optional. Enables navigation to elements within tabs that are currently not visible.
className: (Type: string) Optional. Applies a classname to the root of the component.
defaultPage: (Type: string) Optional. Specifies the default page ID to display upon component initialization.
icons: (Type: array) Optional. Provides a list of icons used for the tabs.
orientation: (Type: string) Optional. Determines whether the tabs are arranged horizontally or vertically.
onPageUpdate: (Type: function) Optional. Executes a callback function when the active page changes.
pages: (Type: array) Optional. Contains the list of pages to be populated from a template.
Pager
The Pager component is a compact tool designed for pagination control. Each page is defined by an offset and a limit, representing the starting position and size of the page respectively. It presents the current page and the total number of elements, typically formatted as "9-12 / 20". In this example, the offset is 8, the limit is 4, and the total number of elements is 20. The Pager includes two navigation buttons, "Previous" and "Next", facilitating movement between pages.
<Pager offset="0" limit="80" total="50" onUpdate="doSomething" />
To read more about An Overview of Owl Components in Odoo 16, refer to our blog An Overview of Owl Components in Odoo 16.