Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. QML and Qt Quick
  4. Accessing child properties in a Component type
Forum Updated to NodeBB v4.3 + New Features

Accessing child properties in a Component type

Scheduled Pinned Locked Moved Unsolved QML and Qt Quick
11 Posts 3 Posters 3.8k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • B BikashRDas

    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.

    KroMignonK Offline
    KroMignonK Offline
    KroMignon
    wrote on last edited by KroMignon
    #2

    @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
                }
            }
        }
    }
    

    It is an old maxim of mine that when you have excluded the impossible, whatever remains, however improbable, must be the truth. (Sherlock Holmes)

    1 Reply Last reply
    0
    • B Offline
      B Offline
      BikashRDas
      wrote on last edited by BikashRDas
      #3

      @KroMignon said in Accessing child properties in a Component type:

      property alias text: tf2.text

      give error, Component objects cannot declare new properties.

      KroMignonK 1 Reply Last reply
      0
      • fcarneyF Offline
        fcarneyF Offline
        fcarney
        wrote on last edited by fcarney
        #4

        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
                    }
        

        C++ is a perfectly valid school of magic.

        B 1 Reply Last reply
        3
        • B BikashRDas

          @KroMignon said in Accessing child properties in a Component type:

          property alias text: tf2.text

          give error, Component objects cannot declare new properties.

          KroMignonK Offline
          KroMignonK Offline
          KroMignon
          wrote on last edited by
          #5

          @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.

          It is an old maxim of mine that when you have excluded the impossible, whatever remains, however improbable, must be the truth. (Sherlock Holmes)

          1 Reply Last reply
          0
          • fcarneyF fcarney

            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
                        }
            
            B Offline
            B Offline
            BikashRDas
            wrote on last edited by BikashRDas
            #6

            @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)
                }
            }
            
            KroMignonK 1 Reply Last reply
            0
            • B BikashRDas

              @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)
                  }
              }
              
              KroMignonK Offline
              KroMignonK Offline
              KroMignon
              wrote on last edited by
              #7

              @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
                  ...
              }
              

              It is an old maxim of mine that when you have excluded the impossible, whatever remains, however improbable, must be the truth. (Sherlock Holmes)

              B 1 Reply Last reply
              1
              • KroMignonK KroMignon

                @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
                    ...
                }
                
                B Offline
                B Offline
                BikashRDas
                wrote on last edited by
                #8

                @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

                KroMignonK 1 Reply Last reply
                0
                • B BikashRDas

                  @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

                  KroMignonK Offline
                  KroMignonK Offline
                  KroMignon
                  wrote on last edited by
                  #9

                  @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.

                  It is an old maxim of mine that when you have excluded the impossible, whatever remains, however improbable, must be the truth. (Sherlock Holmes)

                  B 1 Reply Last reply
                  0
                  • KroMignonK KroMignon

                    @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.

                    B Offline
                    B Offline
                    BikashRDas
                    wrote on last edited by BikashRDas
                    #10

                    @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.

                    KroMignonK 1 Reply Last reply
                    0
                    • B BikashRDas

                      @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.

                      KroMignonK Offline
                      KroMignonK Offline
                      KroMignon
                      wrote on last edited by KroMignon
                      #11

                      @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.

                      It is an old maxim of mine that when you have excluded the impossible, whatever remains, however improbable, must be the truth. (Sherlock Holmes)

                      1 Reply Last reply
                      0

                      • Login

                      • Login or register to search.
                      • First post
                        Last post
                      0
                      • Categories
                      • Recent
                      • Tags
                      • Popular
                      • Users
                      • Groups
                      • Search
                      • Get Qt Extensions
                      • Unsolved