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.3k 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 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