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

Accessing child properties in a Component type

Scheduled Pinned Locked Moved Unsolved QML and Qt Quick
11 Posts 3 Posters 3.6k Views
  • 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 Offline
    B Offline
    BikashRDas
    wrote on last edited by
    #1

    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 1 Reply Last reply
    0
    • 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