[Solved] Dynamic sourceComponent of Loader and changing property of components
-
My requirement is to make a ListView of various types of components reading componentType and its properties from an XML file. I could create the components in the ListView, but could not change/set properties of that component. Below is the xml and qml files.
Components.xml
<?xml version="1.0" encoding="UTF-8" ?> <myComponent> <component> <componentType>component1</componentType> <buttonText>Button1</buttonText> </component> <component> <componentType>component2</componentType> <text>Text1</text> </component> <component> <componentType>component1</componentType> <buttonText>Button2</buttonText> </component> <component> <componentType>component2</componentType> <text>Text2</text> </component> </myComponent>
TestXml.qml
import QtQuick 2.2 import QtQuick.Controls 1.2 import QtQuick.XmlListModel 2.0 Rectangle { width: 200 height: 360 XmlListModel { id: xmlModel source: "Components.xml" query: "/myComponent/component" XmlRole { name: "componentType"; query: "componentType/string()" } XmlRole { name: "buttonText"; query: "buttonText/string()" } XmlRole { name: "txt"; query: "text/string()" } onStatusChanged: { if (status === XmlListModel.Loading) { console.log("Loading...") } if (status === XmlListModel.Ready) { console.log("Loaded " + source) } if (status === XmlListModel.Error) { console.log("Xml Error: " + errorString()) } } } ListView { id: listView anchors.fill: parent model: xmlModel delegate: delegateComponent Component { id: component1 Button { width: parent.width height: 50 // text: buttonText } } Component { id: component2 Text { color: "red" // text: txt } } Component { id: delegateComponent Loader { id: loader width: parent.width sourceComponent: (componentType === "component1") ? component1 : component2 Component.onCompleted: { if (componentType === "component1") { text: buttonText } else if (componentType === "component2") { text: txt } } } } } }
Setting text to buttonText for component1 from Loader Component.onCompleted does not change the text.
I am stuck here. Please help me. -
Hi
Since you are using a Loader you can access the loaded Component using item. So
Component.onCompleted: { if (componentType === "component1") { loader.item.text = buttonText } else if (componentType === "component2") { loader.item.text = txt } }
P.S: The editor in this new forum using markdown syntax. So to add a code you can use ``` (3 backticks) with the same followed at the end.
-
You're Welcome :)
There's a topic combobox at the bottom. It has the "Mark Solved" option. -
Ok understood, so in that case to access delegates from outside ListView, you will need to use children or you can set an item as current item and then access it
listview.currentIndex=1 // 1 is index of delegate, listview = id of ListView console.log(listview.currentItem)
-
I have added the following code to access text of the components
Button { width: 100; height: 40; text: "Get Text"; anchors.top: listView.bottom onClicked: { listView.currentIndex = 2 // or anything else (0 - 3) console.log(listView.currentIndex, listView.currentItem.text) } }
The output (listView.currentItem.text) is alway undefined for any value of listView.currentIndex. Am I doing anything wrong?
-
Ok. Now you have to go further. The currentItem will be the Loader. Try getting children of it
console.log(listView.currentIndex, listView.currentItem.children)
and then try accessing the childrens. It is an array.
-
Well I do see it. Its the bottom entry in the combobox . I'll mark it as solved.
-
Strange I'm to not able to mark it as solved. Clicking doesn't have any effect.