2
votes

I have an EntityBase (Player) that contains Items that contain a Loader which dynamically loads Items (Modules).

Now I would need to access properties of the Player in the Modules.

Printing (console.debug) the Module's parent.parent.parent outputs

Player_QMLTYPE_127(0x2ac147f0)

So I thought I could access the Player's properties by writing parent.parent.parent.myProperty, but none of my properties or child elements show up in the auto-completion list.

Is there something I'm missing? Or is this simply not possible?

1

1 Answers

3
votes

I guess the best approach in that case is using signals and Connections to communicate from within the component towards the outermost items, as described here.

It follows an example copied from the documentation (where MyItem.qml is the item you are dynamically loading):

import QtQuick 2.0
Item {
    width: 100
    height: 100

    Loader {
        id: myLoader
        source: "MyItem.qml"
    }

    Connections {
        target: myLoader.item
        onMessage: console.log(msg)
    }
}

Anyway, the documentation also affirms that:

Alternatively, since MyItem.qml is loaded within the scope of the Loader, it could also directly call any function defined in the Loader or its parent Item.

That's similar to what you are actually trying to do if I've correctly understood the question, but I find that it limits a bit the reusability of the item, for it makes assumption on the surrounding environment and I usually don't like it (of course, that's my idea of design, it doesn't pretend to be the best one).

Note also that the parent property of the Loader points to its visual parent, that could be something different of what you expect. That's because it's actually an Item and it inherits its parent property.

See here for further details.

Instead, to set properties on the loaded item once created, instead of having it accessing them by means of a parent.parent... chain, you can put those properties on the Loader object and access them easily as it follows (that's another example picked up from the documentation):

Item {
    width: 400
    height: 400

    Component {
        id: myComponent
        Text { text: modelIndex }
    }

    ListView {
        anchors.fill: parent
        model: 5

        delegate: Component {
            Loader {
                property int modelIndex: index
                sourceComponent: myComponent
            }
        }
    }
}

In fact, as stated in the documentation, you can:

[...] explicitly set the required information as a property of the Loader (this works because the Loader sets itself as the context object for the component it is loading).

Regarding the scope of a component, from here you can find that:

The component scope is the union of the object ids within the component and the component's root object's properties.