Skip to Content
OWL data_display

Overlay Container

Odoo 19 OWL component — Overlay Container (core)

Live preview Interactive
Source excerpt web/static/src/core/overlay/overlay_container.js
import { Component, onWillDestroy, useChildSubEnv, useRef, useState } from "@odoo/owl";
import { sortBy } from "@web/core/utils/arrays";
import { ErrorHandler } from "@web/core/utils/components";

const OVERLAY_ITEMS = [];
export const OVERLAY_SYMBOL = Symbol("Overlay");

class OverlayItem extends Component {
    static template = "web.OverlayContainer.Item";
    static components = {};
    static props = {
        component: { type: Function },
        props: { type: Object },
        env: { type: Object, optional: true },
    };

    setup() {
        this.rootRef = useRef("rootRef");

        OVERLAY_ITEMS.push(this);
        onWillDestroy(() => {
            const index = OVERLAY_ITEMS.indexOf(this);
            OVERLAY_ITEMS.splice(index, 1);
        });

        if (this.props.env) {
            this.__owl__.childEnv = this.props.env;
        }

        useChildSubEnv({
            [OVERLAY_SYMBOL]: {
                contains: (target) => this.contains(target),
            },
        });
    }

    get subOverlays() {
        return OVERLAY_ITEMS.slice(OVERLAY_ITEMS.indexOf(this));
    }

    contains(target) {
        return (
            this.rootRef.el?.contains(target) ||
            this.subOverlays.some((oi) => oi.rootRef.el?.contains(target))
        );
    }
}

export class OverlayContainer extends Component {
    static template = "web.OverlayContainer";
    static components = { ErrorHandler, OverlayItem };
    static props = { overlays: Object };

    setup() {
        this.root = useRef("root");
        /** @deprecated */
        this.state = useState({ rootEl: null });
    }

    get sortedOverlays() {
        return sortBy(Object.values(this.props.overlays), (overlay) => overlay.sequence);
    }

    isVisible(overlay) {
        return overlay.rootId === this.env?.rootId;
    }

    handleError(overlay, error) {
        overlay.remove();
        Promise.resolve().then(() => {
            throw error;
        });
    }
}
Registry / API
Registry name
OverlayContainer
Category
Module
web
Slug
overlay-container
Nav group
data_display