aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/doc/src/qmllanguageref/syntax/propertybinding.qdoc
blob: 6803901efd22f389310d5039128567053ab6c57e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the documentation of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:FDL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Free Documentation License Usage
** Alternatively, this file may be used under the terms of the GNU Free
** Documentation License version 1.3 as published by the Free Software
** Foundation and appearing in the file included in the packaging of
** this file.  Please review the following information to ensure
** the GNU Free Documentation License version 1.3 requirements
** will be met: http://www.gnu.org/copyleft/fdl.html.
** $QT_END_LICENSE$
**
****************************************************************************/

/*!
\page qtqml-syntax-propertybinding.html
\title Property Binding
\brief binding object properties

To make the fullest use of QML and its built-in support for implementing dynamic object behavioral changes, most QML objects will use \e {property binding}. This is a core feature of QML that allows objects to automatically update their properties in response to changing attributes in other objects or the occurence of some external event.

When an object's property is assigned a value, it can either be assigned a static value, or \e bound to a JavaScript expression. In the first case, the property's value will not change unless a new value is assigned to the property. In the latter case, a \e {property binding} is created and the property's value is automatically updated by the QML engine whenever the value of the evaluated expression changes.


\section1 Overview

To create a property binding, a property is assigned an expression that evaluates to the desired value. At its simplest, an expression may simply be a reference to another object's property. Take the following example, where the blue \l Rectangle's \c height is bound to the height of its parent:

\qml
Rectangle {
    width: 200; height: 200

    Rectangle {
        width: 100; height: parent.height
        color: "blue"
    }
}
\endqml

Whenever the \c height of the parent item changes, the \c height of the blue rectangle will update to be of the same value.

Furthermore, a binding can contain any valid JavaScript expression or
statement, as QML uses a standards compliant JavaScript engine.  Below are
valid bindings that could be substituted for the \c height binding from the
above example:

\code
height: parent.height / 2

height: Math.min(parent.width, parent.height)

height: parent.height > 100 ? parent.height : parent.height/2

height: {
    if (parent.height > 100)
        return parent.height
    else
        return parent.height / 2
}

height: someMethodThatReturnsHeight()
\endcode

Whenever the value of \c parent.height changes, the QML engine will re-evaluate the above expression and assign the blue rectangle's \c width property with the appropriate updated value.

Bindings can access object properties, call methods and use built-in JavaScript objects such as \c Date and \c Math. Here is an example with various valid bindings:

\qml
Column {
    width: 200
    height: 200

    Rectangle {
        width: Math.max(bottomRect.width, parent.width/2)
        height: (parent.height / 3) + 10
        color: "yellow"

        TextInput {
            id: myTextInput
            text: "Hello QML!"
        }
    }

    Rectangle {
        id: bottomRect
        width: 100
        height: 50
        color: myTextInput.text.length <= 10 ? "red" : "blue"
    }
}
\endqml

While syntactically bindings can be of arbitrary complexity, if a binding starts to become overly complex - such as involving multiple lines, or imperative loops - it may be better to refactor the component entirely, or at least factor the binding out into a separate function.


\keyword qml-javascript-assignment
\section1 Creating Property Bindings from JavaScript

Once a property has been bound to an expression, the property is set to be automatically updated as necessary. However, be aware that if the property is later assigned a static value from a JavaScript statement, this will remove the binding.

For example, the \c height of the \l Rectangle below is initially bound to be twice its \c width. However, when the space key is pressed, the \c height value is changed to be three times its \c width. At this point, the \c height is assigned the currently evaluated result of \c width*3 and \e {the height will no longer be automatically updated whenever the width changes}. The assignment of the static value removes the binding.

\qml
import QtQuick 2.0

Rectangle {
    width: 100
    height: width * 2

    focus: true
    Keys.onSpacePressed: {
        height = width * 3
    }
}
\endqml

If the intention is to remove the binding, then this is not a problem. However if the intention is to create a new binding of \c width*3 then the property must be assigned a Qt.binding() value instead. This is done by passing a function to Qt.binding() that returns the desired result:

\qml
import QtQuick 2.0

Rectangle {
    width: 100
    height: width * 2

    focus: true
    Keys.onSpacePressed: {
        height = Qt.binding(function() { return width * 3 })
    }
}
\endqml

Now when the space key is pressed, a new binding of \c width*3 is assigned, instead of simply removing the initial binding.


\section2 Using \c this with Property Binding

When creating a property binding from JavaScript, QML allows the use of the \c
this keyword to refer to the object to which the property binding will be
assigned. This allows one to explicitly refer to a property within an object
when there may be ambiguity about the exact property that should be used for the
binding.

For example, the \c Component.onCompleted handler below is defined within the
scope of the \l Item, and references to \c width within this scope would refer
to the \l Item's width, rather than that of the \l Rectangle. To bind the \l
Rectangle's \c height to its own \c width, the function passed to Qt.binding()
needs to explicitly refer to \c this.width rather than just \c width.

\qml
Item {
    width: 500
    height: 500

    Rectangle {
        id: rect
        width: 100
        color: "yellow"
    }

    Component.onCompleted: {
        rect.height = Qt.binding(function() { return this.width * 2 })
        console.log("rect.height = " + rect.height) // prints 200, not 1000
    }
}
\endqml

In this case, the function could also have referred to \c rect.width rather than
\c this.width.

Note that the value of \c this is not defined outside of its use in property binding.
See \l {JavaScript Environment Restrictions} for details.


*/