QML - addressing an ancestor
qml, qt, qt-quick, qtquick2
Solution
According to http://qt-project.org/doc/qt-4.8/qdeclarativedynamicobjects.html :
- If Qt.createComponent() is used, the creation context is the QDeclarativeContext in which this method is called
- If a Component{} item is defined and createObject() is called on that item, the creation context is the context in which the Component is defined
The problem was that the `createComponent()` function for each subsequent `Node` was called from the context of the `main_container`, thus preventing the descendants from being able to resolve the `dynamic_object` id.
Solved it by moving the code responsible for creating the nested `Node`s to the `Node.qml` file (actually to a javascript file imported by that qml document, but the result is the same).
Problem
I have a container which is being filled with dynamically created components during runtime. Each of those elements (let's call them `DynamicObject`s) has a tree of subelements (`Node`s), also created dynamically. What is more, The `Node` components can be nested inside one another (like a tree structure). Let the container have the `id` parameter set to `"main_container"` and every `DynamicObject` have it set to `"dynamic_object"`. Whenever I try to address the `main_container` from any of the nested `Node` elements it all works fine. The problem is when I try to address the `dynamic_object` from any `Node` other than the root one (the one being the direct descendant / child of the `dynamic_object`). It results in: ReferenceError: dynamic_object is not defined My question is: what might be the cause behind this behaviour? Can it have something to do with the fact those objects are dynamically created? (that was my first thought since I can always address the `main_container` and it is statically declared in the qml code). Code example: (if there is anything missing please let me now in the comments) ``` // Container.qml import "container_logic.js" as Logic Rectangle { id: main_container Keys.onTabPressed: { Logic.createComponent("DynamicObject.qml", {/* some parameters */}); var dynamic_object = Logic.object; Logic.createComponent("Node.qml",{labelText: "asdefg"}, undefined, dynamic_object) var asdefg = Logic.object; Logic.createComponent("Node.qml",{labelText: "tree A"}, undefined, dynamic_object) var tree_a = Logic.object; Logic.createComponent("Node.qml",{labelText: "a"}, undefined, asdefg) var a = Logic.object; Logic.createComponent("Node.qml",{labelText: "s"}, undefined, asdefg) var s = Logic.object; asdefg.subnodes = [a, s] Logic.createComponent("Node.qml",{labelText: "tree B", isInput: false}, undefined, dynamic_object) var tree_b = Logic.object; Logic.createComponent("Node.qml",{labelText: "xyz", isInput: false}, undefined, dynamic_object) var xyz = Logic.object; Logic.createComponent("Node.qml",{labelText: "x", isInput: false}, undefined, xyz) var x = Logic.object; Logic.createComponent("Node.qml",{labelText: "y", isInput: false}, undefined, xyz) var y = Logic.object; Logic.createComponent("Node.qml",{labelText: "z", isInput: false}, undefined, xyz) var z = Logic.object; xyz.subnodes = [x,y,z] dynamic_object.treeLeft = [asdefg, tree_a] dynamic_object.treeRight = [tree_b, xyz] } } // DynamicObject.qml Rectangle { id: dynamic_object property alias treeLeft : tree_left.subnodes property alias treeRight: tree_right.subnodes Rectangle { id: content_area Node { id: tree_left labelText: "left" anchors.left: parent.left } Node { id: tree_right labelText: "right" anchors.right: parent.right } } } // Node.qml ColumnLayout { id: node default property alias subnodes: subnodes_area.data property alias labelText: label.text Rectangle { id: header_area Text { id: label } MouseArea { id: mouse_area anchors.fill: parent hoverEnabled: true onHoveredChanged: { console.debug(main_container) // works fine console.debug(dynamic_object) // **generates the error for all nodes but the root one** } } } ColumnLayout { id: subnodes_area anchors.top: header_area.bottom } } // container_logic var component = null var owner = main_container var object = null var data = null function createComponent(type, info, callback, container) { callback = callback || finishComponent owner = container || main_container if(component != null) { console.log("Error: a component is being loaded at this time"); return; } component = Qt.createComponent(type) data = info if(component.status === Component.Ready) { callback() } else if(component.status === Component.Loading) { component.statusChanged.connect(callback) } else { console.log("Error loading component:", component.errorString()) } } function finishComponent() { if(component.status === Component.Ready) { object = component.createObject(owner, data) if(object === null) { console.log("Error creating object") } } else if(component.status === Component.Error) { console.log("Error loading component:", component.errorString()) } resetData() } function resetData() { component = null; data = null; } ```