Invalid alias reference to a QML component

Solution 1:

Working code below.

The issue is that while the MapQuickItem appears to be in the namespace of your myfile.qml component, it actually is not. Delegates are actually components themselves and start a new namespace. You can think of delegates ending up in a new anonymous component that cannot refer to ids in the surrounding component it appears in.

However, while it can't refer to ids in the surrounding component, it can refer to component ids in the visual hierarchy of components. So, you can refer to root (the id of this file's component itself) in the hierarchy of components that were instantiated when this visual hierarchy is built at run time.

From there, you can advertise the Map component which is private to this component on the root object as an alias and then refer to it via the root reference in MapItemView.

It's all a bit confusing at first but makes sense when you start to realize that components are clusters of QML defined by files, Components, or delegate: definitions. Intra-component id references are fine but external references have to either be passed down as properties or in delegate situations reference through the hierarchy of components upward. And then a child QML object of a component must be advertised as an alias to give external access.

More info here:

https://doc.qt.io/qt-5/qtqml-documents-scope.html

import QtQuick 2.11
import QtQuick.Controls 2.4
import QtLocation 5.11
import QtPositioning 5.11
import QtQuick.Window 2.11

Window {
    id: root; width: 800; height: 600;

    visible: true

    property alias map: map

    Plugin { id: mapPlugin; name: "osm"; }

    ListModel {
        id: myModel
        ListElement { latitude: 48.2351164; longitude: 6.8986936; }
    }

    Map {
        id: map
        anchors.fill: parent
        plugin: mapPlugin
        center: QtPositioning.coordinate(48.2351164, 6.8986936)
        zoomLevel: 19

        property real scale: map.scaleFactor()
        onScaleChanged: {
            console.log(">>> scale from map component", scale);
        }

        // function reimplemented from qdeclarativegeomapquickitem.cpp
        function scaleFactor() {
            return Math.pow(0.5, map.maximumZoomLevel - map.zoomLevel);
        }

        MapItemView {
            model: myModel

            delegate: MapQuickItem {
                anchorPoint.x: myRect.width / 2
                anchorPoint.y: myRect.height / 2
                width: myRect.width
                height: myRect.height

                zoomLevel: map.maximumZoomLevel // set the zoomLevel (1:1 scale)
                coordinate: QtPositioning.coordinate(model.latitude, model.longitude)

                sourceItem: Rectangle {
                    id: myRect

                    readonly property int radius: 50

                    property real scale: root.map.scale
                    onScaleChanged: {
                        myCanvas.requestPaint();
                    }

                    width: radius * 2
                    height: radius * 2
                    color: "transparent"

                    Canvas {
                        id: myCanvas
                        anchors.fill: parent

                        onPaint: {
                            var width = myRect.width;
                            var height = myRect.height;
                            var centreX = width / 2;
                            var centreY = height / 2;
                            var ctx = getContext("2d");
                            ctx.reset();

                            if (scale > 0.1) {
                                ctx.fillStyle = "blue";
                                ctx.globalAlpha = 1;
                                ctx.beginPath();
                                ctx.moveTo(centreX, centreY);
                                ctx.arc(centreX, centreY, myRect.radius, 0, Math.PI * 2, false);
                                ctx.closePath();
                                ctx.fill();
                            }
                        }
                    }
                }
            }
        }
    }
}