Accessing child properties in a Component type
-
Hi All,
Please have a look into the following code snippet.
I have a conditional statement to load one of the component defined below. I can switch between the components by using the Switch button. On switching I want to read the text data from the text field in the already visible component, print the text to console and then switch to the other component.The issue I am facing is to read the text from the text field from the active component.
import QtQuick 2.5 import QtQuick.Layouts 1.3 import QtQuick.Controls 2.2 Item { ColumnLayout { id: cl Switch { id: switchButton checked: true onCheckedChanged: { ***console.log the text from loaded component*** ldr.sourceComponent = checked === true ? c1 : c2 } } Text { id: label text: "Text field" } Loader { id: ldr sourceComponent: switchButton.checked === true ? c1 : c2 } } Component { id: c1 TextField { id: tf1 placeholderText: "Text Input 1" width: 400 height: 50 background: Rectangle { anchors.fill: parent border{ color: "#252525" width: 1 } radius: 2 } } } Component { id: c2 TextField { id: tf2 placeholderText: "Text Input 2" width: 400 height: 50 background: Rectangle { anchors.fill: parent border{ color: "#252525" width: 1 } radius: 2 } } } }
One solution could be to have a string property as part of the root Item element and update the same on change text in any of the text field
Item { property string textData: "" : : : Component { TextField { . . . onTextChanged: { textData = text } } } }
Just wanted to know, if there is any proper solution for this situation.
-
Hi All,
Please have a look into the following code snippet.
I have a conditional statement to load one of the component defined below. I can switch between the components by using the Switch button. On switching I want to read the text data from the text field in the already visible component, print the text to console and then switch to the other component.The issue I am facing is to read the text from the text field from the active component.
import QtQuick 2.5 import QtQuick.Layouts 1.3 import QtQuick.Controls 2.2 Item { ColumnLayout { id: cl Switch { id: switchButton checked: true onCheckedChanged: { ***console.log the text from loaded component*** ldr.sourceComponent = checked === true ? c1 : c2 } } Text { id: label text: "Text field" } Loader { id: ldr sourceComponent: switchButton.checked === true ? c1 : c2 } } Component { id: c1 TextField { id: tf1 placeholderText: "Text Input 1" width: 400 height: 50 background: Rectangle { anchors.fill: parent border{ color: "#252525" width: 1 } radius: 2 } } } Component { id: c2 TextField { id: tf2 placeholderText: "Text Input 2" width: 400 height: 50 background: Rectangle { anchors.fill: parent border{ color: "#252525" width: 1 } radius: 2 } } } }
One solution could be to have a string property as part of the root Item element and update the same on change text in any of the text field
Item { property string textData: "" : : : Component { TextField { . . . onTextChanged: { textData = text } } } }
Just wanted to know, if there is any proper solution for this situation.
@BikashRDas said in Accessing child properties in a Component type:
Just wanted to know, if there is any proper solution for this situation.
I would do it like this:
- add a property alias on each
Component
declaration - setup text value in
onLoaded
event
Like this:
import QtQuick 2.5 import QtQuick.Layouts 1.3 import QtQuick.Controls 2.2 Item { ColumnLayout { id: cl Switch { id: switchButton checked: true onCheckedChanged: { ldr.sourceComponent = checked === true ? c1 : c2 } } Text { id: label text: "Text field" } Loader { id: ldr sourceComponent: switchButton.checked === true ? c1 : c2 onLoaded: { // read current value item.text = label.text // uddate value on text changes item.text = Qt.bindings(Qt.binding(function () { return label.text; }) } } } Component { id: c1 property alias text: tf1.text TextField { id: tf1 placeholderText: "Text Input 1" width: 400 height: 50 background: Rectangle { anchors.fill: parent border{ color: "#252525" width: 1 } radius: 2 } } } Component { id: c2 property alias text: tf2.text TextField { id: tf2 placeholderText: "Text Input 2" width: 400 height: 50 background: Rectangle { anchors.fill: parent border{ color: "#252525" width: 1 } radius: 2 } } } }
- add a property alias on each
-
@KroMignon said in Accessing child properties in a Component type:
property alias text: tf2.text
give error, Component objects cannot declare new properties.
-
@KroMignon said in Accessing child properties in a Component type:
property alias text: tf2.text
give error, Component objects cannot declare new properties.
@BikashRDas said in Accessing child properties in a Component type:
give error, Component objects cannot declare new properties.
Oh my bad, sorry.
In fact it is much easier as @fcarney already explained. -
You can access properties in your top level item inside the component through item:
onCheckedChanged: { console.log(ldr.item.placeholderText) ldr.sourceComponent = checked === true ? c1 : c2 }
@fcarney said in Accessing child properties in a Component type:
console.log(ldr.item.placeholderText)
I replaced the "placeholdertext" with "text". It's working. Thanks.
Is there anyway to make the text data in the active component, available to other QML?
E.g. Suppose the above code is part of MyTextField.qml.
In my main. qml, I am creating an instance of MyTextField component like,in Main.qml
Window { . . . MyTextField { id: mtf . . . } onSomthing : { // mtf.textData refers to the text property of the textfield of active component in MyTextField.qml console.log(mtf.textData) } }
-
@fcarney said in Accessing child properties in a Component type:
console.log(ldr.item.placeholderText)
I replaced the "placeholdertext" with "text". It's working. Thanks.
Is there anyway to make the text data in the active component, available to other QML?
E.g. Suppose the above code is part of MyTextField.qml.
In my main. qml, I am creating an instance of MyTextField component like,in Main.qml
Window { . . . MyTextField { id: mtf . . . } onSomthing : { // mtf.textData refers to the text property of the textfield of active component in MyTextField.qml console.log(mtf.textData) } }
@BikashRDas said in Accessing child properties in a Component type:
Is there anyway to make the text data in the active component, available to other QML?
E.g. Suppose the above code is part of MyTextField.qml.Yes, I think here using
property alias
should do the job:import QtQuick 2.5 import QtQuick.Layouts 1.3 import QtQuick.Controls 2.2 Item { property alias textData: ldr.item.text ... }
-
@BikashRDas said in Accessing child properties in a Component type:
Is there anyway to make the text data in the active component, available to other QML?
E.g. Suppose the above code is part of MyTextField.qml.Yes, I think here using
property alias
should do the job:import QtQuick 2.5 import QtQuick.Layouts 1.3 import QtQuick.Controls 2.2 Item { property alias textData: ldr.item.text ... }
@KroMignon said in Accessing child properties in a Component type:
@BikashRDas said in Accessing child properties in a Component type:
Is there anyway to make the text data in the active component, available to other QML?
E.g. Suppose the above code is part of MyTextField.qml.Yes, I think here using
property alias
should do the job:import QtQuick 2.5 import QtQuick.Layouts 1.3 import QtQuick.Controls 2.2 Item { property alias textData: ldr.item.text ... }
I had tried this earlier. getting this error. qrc:/MyTextBox.qml:7 Invalid alias target location: text
-
@KroMignon said in Accessing child properties in a Component type:
@BikashRDas said in Accessing child properties in a Component type:
Is there anyway to make the text data in the active component, available to other QML?
E.g. Suppose the above code is part of MyTextField.qml.Yes, I think here using
property alias
should do the job:import QtQuick 2.5 import QtQuick.Layouts 1.3 import QtQuick.Controls 2.2 Item { property alias textData: ldr.item.text ... }
I had tried this earlier. getting this error. qrc:/MyTextBox.qml:7 Invalid alias target location: text
@BikashRDas said in Accessing child properties in a Component type:
I had tried this earlier. getting this error. qrc:/MyTextBox.qml:7 Invalid alias target location: text
One other solution would be to use another trick:
import QtQuick 2.5 import QtQuick.Layouts 1.3 import QtQuick.Controls 2.2 Item { property alias textData: ldr.textData ColumnLayout { id: cl Switch { id: switchButton checked: true onCheckedChanged: { console.log(ldr.item.placeholderText) ldr.sourceComponent = checked === true ? c1 : c2 } } Text { id: label text: "Text field" } Loader { id: ldr property var textData sourceComponent: switchButton.checked === true ? c1 : c2 onLoaded: { // read current value textData = item.text // uddate value on text changes textData = Qt.bindings(Qt.binding(function () { return item.text; }) } } } ... }
But you can only read it from outside, not write on it.
-
@BikashRDas said in Accessing child properties in a Component type:
I had tried this earlier. getting this error. qrc:/MyTextBox.qml:7 Invalid alias target location: text
One other solution would be to use another trick:
import QtQuick 2.5 import QtQuick.Layouts 1.3 import QtQuick.Controls 2.2 Item { property alias textData: ldr.textData ColumnLayout { id: cl Switch { id: switchButton checked: true onCheckedChanged: { console.log(ldr.item.placeholderText) ldr.sourceComponent = checked === true ? c1 : c2 } } Text { id: label text: "Text field" } Loader { id: ldr property var textData sourceComponent: switchButton.checked === true ? c1 : c2 onLoaded: { // read current value textData = item.text // uddate value on text changes textData = Qt.bindings(Qt.binding(function () { return item.text; }) } } } ... }
But you can only read it from outside, not write on it.
@KroMignon Okay got it. Thanks for the reply. This trick will solve my requirement. But it would be good to know if there is any appropriate way to be able to do both read and write.
Another question is, hope you have noticed, initially I had posted an approach to use a property as part of root Item and update the same on on text change in the texfield of active components. In the approaches (mentioned by you and one by me) we can have a read access to the text data of the text field. Just wanted to know if there is any advantage/disadvantage of these 2 approaches.
-
@KroMignon Okay got it. Thanks for the reply. This trick will solve my requirement. But it would be good to know if there is any appropriate way to be able to do both read and write.
Another question is, hope you have noticed, initially I had posted an approach to use a property as part of root Item and update the same on on text change in the texfield of active components. In the approaches (mentioned by you and one by me) we can have a read access to the text data of the text field. Just wanted to know if there is any advantage/disadvantage of these 2 approaches.
@BikashRDas If you need to have a read/write access you could do it like this:
import QtQuick 2.5 import QtQuick.Layouts 1.3 import QtQuick.Controls 2.2 Item { id: _root property string textData onTextDataChanged: { if(ldr.status === Loader.Ready) ldr.item.text = textData } ColumnLayout { id: cl Switch { id: switchButton checked: true onCheckedChanged: { console.log(ldr.item.placeholderText) } } Text { id: label text: "Text field" } Loader { id: ldr property string textData onTextDataChanged: _root.textData = textData sourceComponent: switchButton.checked === true ? c1 : c2 onLoaded: { // read current value textData = item.text // update value on text changes textData = Qt.bindings(Qt.binding(function () { return item.text; }) } } } ... }
I think there is no risk about "binding loop", but I don't guarantee anything... Try it out.