You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Odoo16重写MapRenderer类createMarkerPopup函数添加短信按钮失败求助

地图标记弹窗Send SMS按钮点击事件失效问题

我尝试在地图标记的弹窗里添加一个新的Send SMS按钮,但无法给这个按钮绑定点击事件,试了下面的代码没效果,求建议或示例。

(图:地图标记弹窗右下角显示Send SMS按钮)

我尝试的代码

import { MapRenderer } from "@web_map/map_view/map_renderer";

export class SmsMapRenderer extends MapRenderer {
    setup() {
        super.setup();
    }

    createMarkerPopup(markerInfo, latLongOffset = 0) {
        const popup = super.createMarkerPopup(...arguments);
        debugger;
//        const popup = super.createMarkerPopup(markerInfo, latLongOffset);
        const popupFields = popup.getMarkerPopupFields(markerInfo);

        const partner = markerInfo.record.partner;
        const popupHtml1 = renderToString("renewell.sendsmsPopup", {
            fields: popupFields,
            hasFormView: this.props.model.metaData.hasFormView,
        });

        const opensmsBtn = popup
            .getElement()
            .querySelector("button.o-map-renderer--popup-buttons-send_sms");
        const offset = markerInfo.pinInSamePlace * 0.000050;
        if (opensmsBtn) {
            opensmsBtn.onclick = () => {
                const popup = L.popup({ offset: [0, -30] })
                    .setLatLng([
                        partner.partner_latitude + latLongOffset,
                        partner.partner_longitude - latLongOffset,
                    ])
                    .setContent(popupHtml1)
                    .openOn(this.leafletMap);
            };
        }

        return popup;
    }
}

问题原因及解决方案

核心问题

调用父类方法后立即获取DOM元素,此时弹窗的DOM可能还未完全渲染完成,导致找不到按钮;或者后续父类逻辑重新渲染弹窗,清除了你的事件绑定。

修改后的代码示例

import { MapRenderer } from "@web_map/map_view/map_renderer";

export class SmsMapRenderer extends MapRenderer {
    setup() {
        super.setup();
    }

    createMarkerPopup(markerInfo, latLongOffset = 0) {
        const popup = super.createMarkerPopup(...arguments);
        const partner = markerInfo.record.partner;
        const popupFields = popup.getMarkerPopupFields(markerInfo);
        const popupHtml1 = renderToString("renewell.sendsmsPopup", {
            fields: popupFields,
            hasFormView: this.props.model.metaData.hasFormView,
        });
        const offset = markerInfo.pinInSamePlace * 0.000050;

        // 监听弹窗open事件,确保DOM已渲染完成再绑定事件
        popup.on('open', () => {
            const opensmsBtn = popup.getElement().querySelector("button.o-map-renderer--popup-buttons-send_sms");
            if (opensmsBtn) {
                // 用addEventListener替代onclick,避免覆盖其他事件
                opensmsBtn.addEventListener('click', () => {
                    L.popup({ offset: [0, -30] })
                        .setLatLng([
                            partner.partner_latitude + latLongOffset,
                            partner.partner_longitude - latLongOffset,
                        ])
                        .setContent(popupHtml1)
                        .openOn(this.leafletMap);
                });
            }
        });

        // 可选:事件委托方案(更适配动态更新的弹窗内容)
        const popupElement = popup.getElement();
        popupElement.addEventListener('click', (e) => {
            if (e.target.matches("button.o-map-renderer--popup-buttons-send_sms")) {
                L.popup({ offset: [0, -30] })
                    .setLatLng([
                        partner.partner_latitude + latLongOffset,
                        partner.partner_longitude - latLongOffset,
                    ])
                    .setContent(popupHtml1)
                    .openOn(this.leafletMap);
            }
        });

        return popup;
    }
}

关键改进点

  1. 延迟绑定事件:通过监听Leaflet弹窗的open事件,确保弹窗DOM完全渲染后再查找按钮元素。
  2. 使用addEventListener:替代onclick属性,避免覆盖其他可能存在的事件绑定。
  3. 事件委托(可选):将事件绑定到弹窗父元素,即使按钮被动态重新渲染,事件依然有效。

内容的提问来源于stack exchange,提问作者M Tahir Noor

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 05:00:34