QML Loader and loaded item context. Is it a feature or a bug?
-
Hi everybody,
when experimenting with QML I came up to one question. It seems that when QML Loader element loads a component, items within this component can't access properties defined in the loaders' parent and below. Normally QML items form "Context Hierarchy" and you can access properties, defined in "lower" items (parent or parents' parent or etc). But if you use Loader, the only way to access properties in the lower hierarchy levels is property binding.
Just take a look at the sample code:
@import QtQuick 1.1Rectangle {
width: 460
height: 360ListModel{ id: personList ListElement{ name: "Algirdas" ; age: 29 } ListElement{ name: "Tadas" ; age: 29 } ListElement{ name: "Milda" ; age: 2 } ListElement{ name: "Akvile" ; age: 28 } ListElement{ name: "Rasa" ; age: 29 } } Rectangle{ height: 200 width: 200 anchors.centerIn: parent color: "gray" Component{ id: itemDelegate Text { // If I would write here just "name" or "rowModel.name", it would fail! I can access // only properties, defined in the Loader element itself text: rowModel2.name } } ListView{ anchors.fill: parent model: personList delegate: Item { height: 30 width: parent.widthr property variant viewHolder: ListView.view property variant rowIndex: index property variant rowModel: model Row{ anchors.fill: parent spacing: 10 Loader{ // We have to use extra property binding to allow access for the loaded component property variant rowModel2: rowModel sourceComponent: itemDelegate } Text { // This works fine because we do not use Loader here text: name } } } } }
}
@Is it a bug? Or a security feature that if you load a component, it can't have uncontrolled access to properties lower in the element hierarchy? Even if it is a feature, there is no proper explanation in QML Loader docs.
It is very annoying!!! Actually I stepped on this when tried to use TableView from the upcoming QtQuick Desktop Components. In the TableView implementation Loader is used to load custom cell delegates (that can be defined by the user). And in this delegate you don't have access to all the roles of the model that you may need.
-
It just sounds like a bug.
There have been other cases where the instantiated component wasn't properly parented (for example, header component in a visual item model, IIRC).Have you tested it with QtQuick2? It's entirely possible that it was fixed there but not in QtQuick1.
Cheers,
Chris. -
Tried with Qt 5.0 release. The same issue.
It's a bit strange. A guy who is developing QtQuick Desktop Components came up to the same issue when writing TableView. He is using multiple property bindings to pass data to delegates loaded by the Loader. No complains came from him. -
Please file a bug report. It might be intentional (since the component created by the Loader is kind of separate to the context within which the loader exists, as it is managed by the Loader element itself - so conceptually its parent isn't the component higher in the scope chain...) but I think it's probably just a bug.
Cheers,
Chris -
It was intentional and do not assume there were no complaints from my side. :)
The current behavior was introduced in Qt Quick 1.1 and it is here to stay. So for now you will have to forward the properties that you want to have available in your component scope explicitly. There are som valid arguments for that approach, such as to make the loaded components a bit more less coupled and insular.
That said, the behavior is not going to change back at this point but you could file a suggestion to add an optional setting in Loader which results in the old behavior. I have no idea what to call the property or enumeration though.
-
This is exactly what http://qt-project.org/doc/qt-5.0/qtquick/qml-qtquick2-loader.html#using-a-loader-within-a-view-delegate tells about :)
Moving the sub-delegate inside the parent delegate, or to a separate file, should make it work.
With the Desktop Components example that was mentioned, it should be the same.