Tod
Tod

Reputation: 8242

Where are the rules on JavaScript function scope in QML defined?

I'm trying to nail down the specifics of function scope in QML. The examples in the documentation appear to often be incorrect (or incomplete). I'll take a pretty typical example right from the JavaScript Host Environment doc page. I'm using Qt 5.3.

Item {
   width: 200; height: 100
   function mouseAreaClicked(area) {
       console.log("Clicked in area at: " + area.x + ", " + area.y);
   }
   // This will not work because this is undefined
   MouseArea {
       height: 50; width: 200
       onClicked: mouseAreaClicked(this)
   }
   // This will pass area2 to the function
   MouseArea {
       id: area2
       y: 50; height: 50; width: 200
       onClicked: mouseAreaClicked(area2)
   }
}

If I take this and paste it into a new empty project right inside the root ApplicationWindow object it doesn't work. I've seen many examples like this and they all behave the same. The call to the function mouseAreaClicked() generates a Reference Error. I can either move the function up so that it's directly inside the root object, or I can assign an id and call the function through the id.

Is this how this is supposed to work? Are functions only available if they are part of the root object? Is this something that changed recently? Is it releated to the ApplicationWindow object? I can't find any mention of this in the documentation. Also this example is somewhat interesting because the topic under discussion: the this pointer, doesn't behave as described. The code invoked by the first MouseArea works just as well as the code invoked by the 2nd MouseArea so I'm also not sure what to make of that.

Any insight appreciated.

Upvotes: 3

Views: 1359

Answers (1)

CapelliC
CapelliC

Reputation: 60034

I think that the point it's the definition of 'processing unit'. Probably (I will check this later) when you paste some code intended to reside in a file.qml - then intended to (re)define a somewhat autonomous component - you change the nesting scope, and - I deduce from the sample you report, and my experience - only root' properties are visible unqualified in deeply nested levels. I've tested so far that the obvious 'explicit qualification'

...
  MouseArea {
       id: area2
       y: 50; height: 50; width: 200
       onClicked: parent.mouseAreaClicked(area2)
   }
...

works as expected. Maybe they should take your question into account, and correct the sample code, or explain why you shouldn't copy/pastethat snippet. Overall, I find your question reasonable.

FWIW, I have code that - inside derived QML components - calls utilities that I placed in the root of my application. Here is my utility

-- main file

ApplicationWindow {
    ...
    // utility to assign multiple members by name
    function assign(target, source) {
        for (var k in source)
            target[k] = source[k]
    }
    ...
}

-- component file(s)

MouseArea {

    ...
    anchors.fill: parent
    drag.target: dr

    onClicked: {
        //console.log("onClicked")
        var i = {x:mouse.x, y:mouse.y, visible:true, width:10, height:10}
        assign(dr, i)
        assign(area, i)
    }
    ...
 }

Upvotes: 1

Related Questions