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. QML Loader, passing arguments to source
Forum Updated to NodeBB v4.3 + New Features

QML Loader, passing arguments to source

Scheduled Pinned Locked Moved Solved QML and Qt Quick
13 Posts 4 Posters 2.1k Views 2 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.
  • mzimmersM Offline
    mzimmersM Offline
    mzimmers
    wrote on last edited by
    #1

    Hi all -

    I have a page that will select a sub-page to display based on a property. I'm using a Loader for this.
    This works:

    required property Equipment equipment
    
    Loader {
        id: loader
        
        Component.onCompleted: {
            var sourceFile
            switch (equipmentCopy.category) {
            case NgaUI.CATEGORY_VSP:
                sourceFile = "edits/VspEdit.qml"
                break;
            ...
            default:
                sourceFile = ""
                break;
            }
            setSource(sourceFile,
                      {
                          "equipment": equipmentEdit.equipment,
                      })
        }
    }
    

    What I'd prefer to do is something like this (for brevity and clarity):

    required property Equipment equipment
    
    Loader {
        id: loader
    	source: {
            switch (equipmentCopy.category) {
                case NgaUI.CATEGORY_VSP:
    				"edits/VspEdit.qml"
                ...
                default:
                    return null
            }
            equipment: equipmentEdit.equipment
        }
    }
    

    But I get a runtime error: "Unable to assign Equipment to QUrl." So, it appears that I can't pass arguments this way.

    So...is it even possible to specify arguments within my Loader definition? Or, do I need to use the onCompleted() method?

    Thanks...

    J.HilkJ 1 Reply Last reply
    0
    • GrecKoG Offline
      GrecKoG Offline
      GrecKo
      Qt Champions 2018
      wrote on last edited by
      #12

      required properties can't work in Loader's components unless you call setSource

      https://bugreports.qt.io/browse/QTBUG-125072
      https://bugreports.qt.io/browse/QTBUG-93086

      A workaround is mentioned at the end of the description here : https://bugreports.qt.io/browse/QTBUG-125071

      Using StackView could also be an alternative if it fits your use case.

      Also is this for a delegate? A DelegateChooser could be a good solution.

      mzimmersM 1 Reply Last reply
      1
      • A Offline
        A Offline
        ankou29666
        wrote on last edited by
        #2

        If i'm understanding properly your need :

        https://www.youtube.com/watch?v=nteJeojg07k at 8min50s

        1 Reply Last reply
        1
        • mzimmersM mzimmers

          Hi all -

          I have a page that will select a sub-page to display based on a property. I'm using a Loader for this.
          This works:

          required property Equipment equipment
          
          Loader {
              id: loader
              
              Component.onCompleted: {
                  var sourceFile
                  switch (equipmentCopy.category) {
                  case NgaUI.CATEGORY_VSP:
                      sourceFile = "edits/VspEdit.qml"
                      break;
                  ...
                  default:
                      sourceFile = ""
                      break;
                  }
                  setSource(sourceFile,
                            {
                                "equipment": equipmentEdit.equipment,
                            })
              }
          }
          

          What I'd prefer to do is something like this (for brevity and clarity):

          required property Equipment equipment
          
          Loader {
              id: loader
          	source: {
                  switch (equipmentCopy.category) {
                      case NgaUI.CATEGORY_VSP:
          				"edits/VspEdit.qml"
                      ...
                      default:
                          return null
                  }
                  equipment: equipmentEdit.equipment
              }
          }
          

          But I get a runtime error: "Unable to assign Equipment to QUrl." So, it appears that I can't pass arguments this way.

          So...is it even possible to specify arguments within my Loader definition? Or, do I need to use the onCompleted() method?

          Thanks...

          J.HilkJ Offline
          J.HilkJ Offline
          J.Hilk
          Moderators
          wrote on last edited by J.Hilk
          #3

          @mzimmers Connections and Bindings are your friend hier

          //From Component to Outside
          Connections{
              target: loader.item
              enabled: loader.status == Loader.Ready
              function mySignal(myArgument) {
                  myOutsideProperty = myArgument
              }
          }
          //from file to Loader Component:
          Binding {
              target:loader.item
              property:"myComponentPropert"
              value: myOutsideProperty
              when: loader.status == Loader.Ready
          }
          

          Also IIRC properties defined in the scope of the Loader are also passed to the Component loader. Not 100% on this though


          Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


          Q: What's that?
          A: It's blue light.
          Q: What does it do?
          A: It turns blue.

          1 Reply Last reply
          1
          • mzimmersM Offline
            mzimmersM Offline
            mzimmers
            wrote on last edited by
            #4

            @ankou29666 @J-Hilk thanks for the replies - the KDAB tutorial seems to agree with what @J-Hilk posted. Somehow, though, it's not working for me. Here's what I did:

            Pane {
                id: equipmentEdit
                required property Equipment equipment
            
                Loader {
                    id: loader
                        source: {
                            switch (equipmentCopy.category) {
                                case NgaUI.CATEGORY_VSP:
                                    "edits/VspEdit.qml"
                                default:
                                    return null
                            }
                        }
                    }
                }
                Binding {
                    target: loader.item
                    property: "equipment"
                    value: equipmentEdit.equipment
                    when: loader.status === Loader.Ready
                }
            }
            

            in "edits/VspEdit.qml," the equipment property is required. At run-time, I get an error:

            Required property equipment was not initialized.
            

            Did I miss a step? Or, is this possibly a race condition where the QML engine attempts to initialize the property before the Loader is ready?

            Thanks...

            J.HilkJ 1 Reply Last reply
            0
            • A Offline
              A Offline
              ankou29666
              wrote on last edited by
              #5

              hmmm I see nothing in the doc on how to deal with it when the source property belongs to the Binding's parent.

              have you tried value: equipment in the Binding ?

              or

              when: loader.source==="edits/VspEdit.qml" && loader.status===Loader.Ready"
              

              if ever relevant depending on other cases for the switch ?

              mzimmersM 1 Reply Last reply
              0
              • A ankou29666

                hmmm I see nothing in the doc on how to deal with it when the source property belongs to the Binding's parent.

                have you tried value: equipment in the Binding ?

                or

                when: loader.source==="edits/VspEdit.qml" && loader.status===Loader.Ready"
                

                if ever relevant depending on other cases for the switch ?

                mzimmersM Offline
                mzimmersM Offline
                mzimmers
                wrote on last edited by
                #6

                @ankou29666 said in QML Loader, passing arguments to source:

                have you tried value: equipment in the Binding

                Yes, and I even created properties inside the loader, and used those instead -- same result.

                1 Reply Last reply
                0
                • A Offline
                  A Offline
                  ankou29666
                  wrote on last edited by ankou29666
                  #7

                  and what happens if you remove the requirement for that "equipment" property inside your "edits/VspEdit.qml" ?

                  or maybe just when: loader.source==="edits/VspEdit.qml", without checking the status ?

                  I'm actually thinking about a race condition as you suggested.
                  As far as I understand,

                  • the component requires the property binding BEFORE it's instantiation, but
                  • the binding is made only AFTER the loader has done the job, due to the "when" condition
                  • and thus the binding is made AFTER the instantiation of the component, which is contradictory with the first statement

                  so my guess would be removing the loader.status case in the "when" clause.

                  mzimmersM 1 Reply Last reply
                  0
                  • A ankou29666

                    and what happens if you remove the requirement for that "equipment" property inside your "edits/VspEdit.qml" ?

                    or maybe just when: loader.source==="edits/VspEdit.qml", without checking the status ?

                    I'm actually thinking about a race condition as you suggested.
                    As far as I understand,

                    • the component requires the property binding BEFORE it's instantiation, but
                    • the binding is made only AFTER the loader has done the job, due to the "when" condition
                    • and thus the binding is made AFTER the instantiation of the component, which is contradictory with the first statement

                    so my guess would be removing the loader.status case in the "when" clause.

                    mzimmersM Offline
                    mzimmersM Offline
                    mzimmers
                    wrote on last edited by
                    #8

                    @ankou29666 said in QML Loader, passing arguments to source:

                    so my guess would be removing the loader.status case in the "when" clause.

                    That was my guess too, but it doesn't work. Maybe a loader isn't what I should be using here. I'll look at alternatives.

                    1 Reply Last reply
                    0
                    • mzimmersM mzimmers

                      @ankou29666 @J-Hilk thanks for the replies - the KDAB tutorial seems to agree with what @J-Hilk posted. Somehow, though, it's not working for me. Here's what I did:

                      Pane {
                          id: equipmentEdit
                          required property Equipment equipment
                      
                          Loader {
                              id: loader
                                  source: {
                                      switch (equipmentCopy.category) {
                                          case NgaUI.CATEGORY_VSP:
                                              "edits/VspEdit.qml"
                                          default:
                                              return null
                                      }
                                  }
                              }
                          }
                          Binding {
                              target: loader.item
                              property: "equipment"
                              value: equipmentEdit.equipment
                              when: loader.status === Loader.Ready
                          }
                      }
                      

                      in "edits/VspEdit.qml," the equipment property is required. At run-time, I get an error:

                      Required property equipment was not initialized.
                      

                      Did I miss a step? Or, is this possibly a race condition where the QML engine attempts to initialize the property before the Loader is ready?

                      Thanks...

                      J.HilkJ Offline
                      J.HilkJ Offline
                      J.Hilk
                      Moderators
                      wrote on last edited by J.Hilk
                      #9

                      @mzimmers I noticed some strange behaviour with bindings since I startet working with them in Qt6 and had undefined's when they clearly shouldn't be. A work around that I found for me would be:

                      Pane {
                          id: equipmentEdit
                          required property Equipment equipment
                          property bool completed: false
                          Component.onCompleted: equipmentEdit.completed = true
                      
                          Loader {
                              id: loader
                                  source: {
                                      switch (equipmentCopy.category) {
                                          case NgaUI.CATEGORY_VSP:
                                              "edits/VspEdit.qml"
                                          default:
                                              return null
                                      }
                                  }
                              }
                          }
                          Binding {
                              target: loader.item
                              property: "equipment"
                              value: equipmentEdit.equipment
                              when: loader.status === Loader.Ready && equipmentEdit.completed 
                          }
                      }
                      

                      Don't know why, I never had to rely on this tricks before


                      Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


                      Q: What's that?
                      A: It's blue light.
                      Q: What does it do?
                      A: It turns blue.

                      mzimmersM 1 Reply Last reply
                      0
                      • J.HilkJ J.Hilk

                        @mzimmers I noticed some strange behaviour with bindings since I startet working with them in Qt6 and had undefined's when they clearly shouldn't be. A work around that I found for me would be:

                        Pane {
                            id: equipmentEdit
                            required property Equipment equipment
                            property bool completed: false
                            Component.onCompleted: equipmentEdit.completed = true
                        
                            Loader {
                                id: loader
                                    source: {
                                        switch (equipmentCopy.category) {
                                            case NgaUI.CATEGORY_VSP:
                                                "edits/VspEdit.qml"
                                            default:
                                                return null
                                        }
                                    }
                                }
                            }
                            Binding {
                                target: loader.item
                                property: "equipment"
                                value: equipmentEdit.equipment
                                when: loader.status === Loader.Ready && equipmentEdit.completed 
                            }
                        }
                        

                        Don't know why, I never had to rely on this tricks before

                        mzimmersM Offline
                        mzimmersM Offline
                        mzimmers
                        wrote on last edited by
                        #10

                        @J-Hilk it was worth a try, but still didn't work. As I said above, maybe I don't need a Loader here - I just need something to insert one of my Components into a screen, selecting the component based on a property of one of the properties in my main Component (in this case, equipmentEdit.category).

                        J.HilkJ 1 Reply Last reply
                        0
                        • mzimmersM mzimmers

                          @J-Hilk it was worth a try, but still didn't work. As I said above, maybe I don't need a Loader here - I just need something to insert one of my Components into a screen, selecting the component based on a property of one of the properties in my main Component (in this case, equipmentEdit.category).

                          J.HilkJ Offline
                          J.HilkJ Offline
                          J.Hilk
                          Moderators
                          wrote on last edited by
                          #11

                          @mzimmers Ah I missunderstood

                          you have your equipment property in the component markt as required ! Right ?

                          thats an easy fix, set your loader active property to false

                          and set it to true in the parent on the onCompleted signal


                          Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


                          Q: What's that?
                          A: It's blue light.
                          Q: What does it do?
                          A: It turns blue.

                          1 Reply Last reply
                          0
                          • GrecKoG Offline
                            GrecKoG Offline
                            GrecKo
                            Qt Champions 2018
                            wrote on last edited by
                            #12

                            required properties can't work in Loader's components unless you call setSource

                            https://bugreports.qt.io/browse/QTBUG-125072
                            https://bugreports.qt.io/browse/QTBUG-93086

                            A workaround is mentioned at the end of the description here : https://bugreports.qt.io/browse/QTBUG-125071

                            Using StackView could also be an alternative if it fits your use case.

                            Also is this for a delegate? A DelegateChooser could be a good solution.

                            mzimmersM 1 Reply Last reply
                            1
                            • GrecKoG GrecKo

                              required properties can't work in Loader's components unless you call setSource

                              https://bugreports.qt.io/browse/QTBUG-125072
                              https://bugreports.qt.io/browse/QTBUG-93086

                              A workaround is mentioned at the end of the description here : https://bugreports.qt.io/browse/QTBUG-125071

                              Using StackView could also be an alternative if it fits your use case.

                              Also is this for a delegate? A DelegateChooser could be a good solution.

                              mzimmersM Offline
                              mzimmersM Offline
                              mzimmers
                              wrote on last edited by
                              #13

                              @GrecKo said in QML Loader, passing arguments to source:

                              required properties can't work in Loader's components unless you call setSource

                              Well, that's that. Looks like I'll be using setSource() after all; a Loader is better for my use case than a StackView.

                              Thanks to all who looked at this.

                              1 Reply Last reply
                              0
                              • mzimmersM mzimmers has marked this topic as solved on

                              • Login

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