Enable Dark Mode!
how-to-use-the-useexternallistener-hook-in-odoo-18.jpg
By: Swaraj R

How to use the useExternalListener hook in Odoo 18

Technical Odoo 18 Odoo Enterprises Odoo Community

In this blog, we are going to discuss the useExternalListener hook in Odoo 18, a powerful, modern day OWL hook. This is mainly used when a component needs to do DOM Events on element(s) that are not part of its hierarchy; we can use the useExternalListener hook. It will correctly add and remove the event listener whenever the component is mounted and unmounted.

The basic syntax to follow while using these hooks is,

In the constructor of the OWL component that needs to be notified, which means in the setup of the component, we need to define it as described below.

setup() {
useExternalListener(window, "resize", this.onWindowResized);
}

Let's discuss how to perform actions or make DOM manipulation based on the window resize events. Let’s create a custom UI and a snippet in it that shows the window width and height, and change the background color based on the window height.

First, let’s create custom_component.js under your module static/src/js like the one below.

/** @odoo-module **/
import { registry } from "@web/core/registry";
import { Component, useState, useRef } from "@odoo/owl";
import { useExternalListener, useEffect } from "@odoo/owl";
class CustomAction extends Component {
    static template = "custom_owl_action.CustomAction";
    setup() {
        this.state = useState({
            message: "Window Size Tracker",
            width: window.innerWidth,
            height: window.innerHeight,
        });
        this.root = useRef("main_custom_section");
        useExternalListener(window, "resize", this.onWindowResized);
        useEffect(
            () => {
                this.updateBackgroundByWidth();
            },
            () => [this.state.width]
        );
    }
    updateBackgroundByWidth() {
        const el = this.root.el;
        if (!el) {
            return;
        }
        let color = "";
        if (this.state.width > 1200) {
            color = "#d4edda";   // light green
        } else if (this.state.width > 992) {
            color = "#fff3cd";   // light yellow
        } else if (this.state.width > 768) {
            color = "#ffe5b4";   // orange warning
        } else {
            color = "#f8d7da";   // light red
        }
        el.style.backgroundColor = color;
        el.style.transition = "background-color 0.4s ease";
    }
    onWindowResized() {
        this.state.width = window.innerWidth;
        this.state.height = window.innerHeight;
    }
}
registry.category("actions").add("custom_owl_action.action_js", CustomAction);

Now, create custom_component.xml under your module static/src/xml, like the one below.

<?xml version="1.0" encoding="UTF-8"?>
<templates xml:space="preserve">
    <t t-name="custom_owl_action.CustomAction">
        <div style="display:flex; justify-content:center; align-items:center; height:100vh; width:100%;"
             t-ref="main_custom_section">
            <div class="o_custom_action text-center"
                 style="border:1px solid #ddd; border-radius:10px; padding:30px; min-width:350px; background:white; box-shadow:0 4px 10px rgba(0,0,0,0.1);">
                <h1 class="text-primary">Custom OWL Client Action</h1>
                <p t-esc="state.message" style="margin-top:15px;"/>
                <div style="margin-top:20px; padding:15px; border:1px solid #eee; border-radius:8px; background:#f8f9fa;">
                    <div style="font-weight:bold; margin-bottom:10px;">Window Details</div>
                    <div style="margin-bottom:8px;">
                        Width:
                        <span t-esc="state.width"/>
                    </div>
                    <div>
                        Height:
                        <span t-esc="state.height"/>
                    </div>
                </div>
            </div>
        </div>
    </t>
</templates>

Create the your_module_name_actions.xml under the views directory.

<?xml version="1.0" encoding="utf-8"?>
<odoo>
    
    <!-- Client action -->
    <record id="action_custom_owl" model="ir.actions.client">
        <field name="name">Custom OWL Action</field>
        <field name="tag">custom_owl_action.action_js</field>
    </record>
    
    <!-- Parent menu -->
    <menuitem id="menu_custom_owl_root"
              name="OWL Action"
              sequence="10"/>
    
    <!-- child menu -->
    <menuitem id="menu_custom_owl_action"
              name="My OWL Action"
              parent="menu_custom_owl_root"
              action="action_custom_owl"
              sequence="10"/>
</odoo>

In this blog, we have seen a use case of the useExternalListener, recommended for attaching external event listeners to the external DOM elements. The listener is added when the component is mounted and removed when the component is unmounted. Mainly used when the component has to perform some actions based on the events outside the component's scope.

To read more about How to Use the EmojiPicker and FileViewer Hook in Odoo 18, refer to our blog How to Use the EmojiPicker and FileViewer Hook in Odoo 18.


Frequently Asked Questions

Does it automatically remove the event listener when the component is unmounted?

Yes, it removes the event listener when the component is unmounted.

Can I use multiple useExternalListener?

Yes, you can use multiple useExternalListener.

Can I detect window resize?

Yes, you can detect window resize.

Can I listen to keyboard events?

Yes, you can listen to keyboard events.

If you need any assistance in odoo, we are online, please chat with us.



0
Comments



Leave a comment



whatsapp_icon
location

Calicut

Cybrosys Technologies Pvt. Ltd.
Neospace, Kinfra Techno Park
Kakkancherry, Calicut
Kerala, India - 673635

location

Kochi

Cybrosys Technologies Pvt. Ltd.
1st Floor, Thapasya Building,
Infopark, Kakkanad,
Kochi, India - 682030.

location

Bangalore

Cybrosys Techno Solutions
The Estate, 8th Floor,
Dickenson Road,
Bangalore, India - 560042

Send Us A Message