Qt Forum

    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    • Unsolved

    How to get eval() to operate in the scope of QML element

    QML and Qt Quick
    2
    10
    2151
    Loading More Posts
    • 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.
    • Q
      qttester5 last edited by

      If I have some JS code as text and I call it in eval(), I can then use the functions defined by this statement only in the scope of where the eval() occurred. As far as I can tell, this means that any new JS definitions created from the eval are invisible to the rest of QML. Consider this QML signal handler:

      @
      Item {
      id: testitem
      onThesourceChanged: {
      eval(thesource)
      testfunction()
      }
      }@

      The testfunciton() was defined in the text "thesource" and does indeed work; but it is not in the scope of the QML element and therefore cannot be called ever again, as far as I can see. I've tried various ideas like putting the eval() in a function, or inside Component.onCompleted, etc, but I can't seem to figure out how to get anything created by the eval() to be recognized as part of the parent QML element.

      For example I want to be able to call testitem.testfunction() -- but it is not defined outside the scope of this handler.

      Can anyone assist?

      1 Reply Last reply Reply Quote 0
      • X
        Xander84 last edited by

        Hi, maybe a little bit far fetched, but the function might be garbage collected after you call it, since you just define it inside your "onThesourceChanged" slot and call it once, it seems like a local function in a function!? Just an idea :)

        if you use eval your get somethging like this:
        @
        Item {
        id: testitem
        onThesourceChanged: {
        var testfunction = function() { ... } // after eval -> local function ?
        testfunction()
        }
        }
        @

        1 Reply Last reply Reply Quote 0
        • Q
          qttester5 last edited by

          You are probably right, but the question is, how to get the definitions that appear inside the text that is evaluated with eval() to actually be attached to a QML element and persist?

          1 Reply Last reply Reply Quote 0
          • X
            Xander84 last edited by

            Well simple solution would be so save a reference to the function, so you can call it from outside, e.g.
            @
            Item {
            id: testitem
            property var testfunction // use this property to save the function you generate in your eval
            onThesourceChanged: {
            eval(thesource)
            testfunction()
            }
            }
            @
            I can't think of any easier way at the moment, but if you only have once function you can do it like this, it gets a little more complicated if you generate multiple dynamic functions...
            you can set the property from the source code your provide to eval or better return it in the source code ans use it like
            @
            testfunction = eval(thesource)
            @
            that should work, I have no idea if there is a way to define dynamic functions or properties in QML. Maybe you can research that or somebody else knows that, but I am not aware of something like that.

            1 Reply Last reply Reply Quote 0
            • Q
              qttester5 last edited by

              I have many functions, and their names and quantity will vary; I'm essentially loading a whole JS program at runtime via the eval. So I can't assign individual vars like this, though it is a good idea.

              1 Reply Last reply Reply Quote 0
              • X
                Xander84 last edited by

                Ok then I have another idea, if you load a whole script do you have control over it somehow? I mean you could wrap it inside a JS object and assign that to a property?
                So same code as in my last post, just the property name changed
                @
                Item {
                id: testitem
                property var myFunctions // use this property to store your object with all functions
                onThesourceChanged: {
                myFunctions = eval(thesource)
                myFunctions.testfunction()
                }
                }
                @
                and your "thesource" looks something like
                @
                return {
                testfunction: function() { ... },
                testfunction2: function() { ... },
                testfunction3: function() { ... }
                ...
                }
                @

                Still this sounds a little weird, but I really have no idea if you can create dynamic functions property with QML. What you need is a JS lib maybe, like if you create a real .js file in QML and import it like
                @
                import "YourFunctions.js" as YourFunctions
                @
                again no idea if it would be possible to load a dynamically generated JS file like that, but that would be the best answer, if possible. And not assign the functions to a QML Item.

                1 Reply Last reply Reply Quote 0
                • Q
                  qttester5 last edited by

                  A var needs to be in JSON format, right? If you have a JS file with normal standalone definitions, those will not be assigned to JSON keys, so you can't assign the entire file to a var. I wish you could, though.

                  My JS file is just a normal JS program. I cannot wrap it inside anything or assign each definition to a JSON key. I can import it in QML fine, but I want to be able to refresh this import dynamically, and using eval() seems to be one way to do this, if only I can get the scope to work out.

                  1 Reply Last reply Reply Quote 0
                  • X
                    Xander84 last edited by

                    I don' think the "property var" needs to be in JSON format, since Qt 5 at least it can be any JavaScript value you can assign to a local "var". before Qt 5 you couldn't e event assign a function to a "property" as far as I know, but I have done that in my app (Qt 5.2.1).
                    Well maybe someone else has an idea with your problem, if you can't use it like this. :/

                    1 Reply Last reply Reply Quote 0
                    • Q
                      qttester5 last edited by

                      It would be awesome if the import statement at the top of a QML file could just be reloaded at runtime. I can't find any way to do that either. It would solve my issue.

                      1 Reply Last reply Reply Quote 0
                      • Q
                        qttester5 last edited by

                        I found the solution. Using Qt.include() allows for dynamic reloading of a javascript file at runtime, even if that javascript file has changed.

                        1 Reply Last reply Reply Quote 0
                        • First post
                          Last post