I'm trying to assing a Component itself to one of its property, and then passing that property to a function inside an external file (import "Scripts.js" as Scripts
)
The first thing that came to my mind was (in my opinion) the most obvious method:
//MyComponent.qml
Item {
id: comp
// property var target: comp
// doesn't work either
property var target: this
...
onActiveFocusChanged: {
// Scripts.foo(this)
// and Scripts.foo(tf)
// don't work either
if(this.activeFocus) {
Scripts.foo(target)
}
}
}
But that doesn't work (the window crashes after giving activeFocus to the Component).
So, I assigned undefined to the target as default:
...
property var target: undefined
...
and then assigned the Component itself when declared:
MyComponent {
id: myComponent
...
target: this
// target: myComponent
// also works
...
}
When the activeFocus is triggered, everything works fine. Can someone tell me why / what I'm doing wrong?
It's impossible to assing to a component property the component itself?
And why it's not impossible to do this after declared?
CodePudding user response:
As folibis already commented you should use id
s instead of this
keyword. Have a look at the following SO post.
import QtQuick
Window {
id: root
width: 800
height: 600
visible: true
title: qsTr("Hello Component")
function foo(parameter) { console.log(parameter) }
component MyComponent : Item {
id: component
property var target: component
Component.onCompleted: {
root.foo(component.target)
root.foo(component)
}
}
MyComponent {}
MyComponent { target: root }
}
This works without an issue.
import QtQuick
Window {
id: root
width: 800
height: 600
visible: true
title: qsTr("Hello Component")
function foo(parameter) { console.log(parameter) }
component MyComponent : Item {
id: component
property var target: component
onActiveFocusChanged: {
if(component.activeFocus)
root.foo(component.target)
}
}
MyComponent { id: test }
Component.onCompleted: test.forceActiveFocus()
}
CodePudding user response:
The this
keyword has special meaning in Javascript and can change it's meaning depending on context. Since you declared it as target: this
you made it property bind so that every change to this
will trigger a new value in target
. To work around that problem, you can ensure that you capture this
exactly once with:
// MyComponent.qml
import QtQuick
import QtQuick.Controls
Item {
property Item target
Component.onCompleted: target = this
}
Alternatively, if you want to keep your code clean of imperative code, you can make use of parent
in the following way:
// MyComponent.qml
import QtQuick
import QtQuick.Controls
Item {
readonly property alias target: internal.target
Item {
id: internal
property Item target: parent
}
}
In the above, internal
is clearly a subitem of Item
and therefore, there can only be one meaning for parent
which is your original item itself.