1// Copyright (C) 2017 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
5\page qtqml-syntax-propertybinding.html
7\brief binding object properties
9An object's property can be assigned a static value which stays constant until it
10is explicitly assigned a new value. However, to make the fullest use of QML and its
11built-in support for dynamic object behaviors, most QML objects use \e {property bindings}.
13Property bindings are a core feature of QML that lets developers specify relationships
14between different object properties. When a property's \e dependencies change in
15value, the property is automatically updated according to the specified relationship.
17Behind the scenes, the QML engine monitors the property's dependencies (that is,
18the variables in the binding expression). When a change is detected, the QML engine
19re-evaluates the binding expression and applies the new result to the property.
23To create a property binding, a property is assigned a JavaScript expression that
24evaluates to the desired value. At its simplest, a binding may be a reference to
25another property. Take the following example, where the blue \l Rectangle's height
26is bound to the height of its parent:
30 width: 200; height: 200
40Whenever the height of the parent rectangle changes, the height of the blue
41rectangle automatically updates to be of the same value.
43A binding can contain any valid JavaScript expression or statement, as QML uses
44a standards compliant JavaScript engine. Bindings can access object properties,
45call methods and use built-in JavaScript objects such as \c Date and \c Math.
46Below are other possible bindings for the previous example:
49height: parent.height / 2
51height: Math.min(parent.width, parent.height)
53height: parent.height > 100 ? parent.height : parent.height/2
56 if (parent.height > 100)
59 return parent.height / 2
62height: someMethodThatReturnsHeight()
65Below is a more complex example involving more objects and types:
75 width: Math.max(bottomRect.width, parent.width/2)
76 height: (parent.height / 3) + 10
89 color: myTextInput.text.length <= 10 ? "red" : "blue"
94In the previous example,
96\li \c topRect.width depends on \c bottomRect.width and \c column.width
97\li \c topRect.height depends on \c column.height
98\li \c bottomRect.color depends on \c myTextInput.text.length
101Syntactically, bindings are allowed to be of arbitrary complexity. However, if
102a binding is overly complex - such as involving multiple lines, or imperative
103loops - it could indicate that the binding is being used for more than describing
104property relationships. Complex bindings can reduce code performance, readability,
105and maintainability. It may be a good idea to redesign components that have
106complex bindings, or at least factor the binding out into a separate function.
107As a general rule, users should not rely on the evaluation order of bindings.
109\sa {Positioning with Anchors}
112\target qml-javascript-assignment
113\section1 Creating Property Bindings from JavaScript
115A property with a binding is automatically updated as necessary. However, if the
116property is later assigned a static value from a JavaScript statement, the binding
119For example, the \l Rectangle below initially ensures that its \c height is always
120twice its \c width. However, when the space key is pressed, the current value
121of \c {width*3} will be assigned to \c height as a \e static value. After that,
122\e {the \c height will remain fixed at this value, even if the \c width changes}.
123The assignment of the static value removes the binding.
133 Keys.onSpacePressed: {
139If the intention is to give the rectangle a fixed height and stop automatic
140updates, then this is not a problem. However, if the intention is to establish
141a new relationship between \c width and \c height, then the new binding
142expression must be wrapped in the Qt.binding() function instead:
152 Keys.onSpacePressed: {
153 height = Qt.binding(function() { return width * 3 })
158Now, after the space key is pressed, the rectangle's height will continue
159auto-updating to always be three times its width.
161\section3 Debugging overwriting of bindings
163A common cause of bugs in QML applications is accidentally overwriting bindings
164with static values from JavaScript statements. To help developers track down
165problems of this kind, the QML engine is able to emit messages whenever a
166binding is lost due to imperative assignments.
168In order to generate such messages, you need to enable the informational output
169for the \c{qt.qml.binding.removal} logging category, for instance by calling:
172QLoggingCategory::setFilterRules(QStringLiteral("qt.qml.binding.removal.info=true"));
175Please refer to the QLoggingCategory documentation for more information about
176enabling output from logging categories.
178Note that is perfectly reasonable in some circumstances to overwrite bindings.
179Any message generated by the QML engine should be treated as a diagnostic aid,
180and not necessarily as evidence of a problem without further investigation.
182\section2 Using \c this with Property Binding
184When creating a property binding from JavaScript, the \c this keyword can be used
185to refer to the object which receives the binding. This is helpful for resolving
186ambiguities with property names.
188For example, the \c Component.onCompleted handler below is defined within the
189scope of the \l Item. In this scope, \c width refers to the \l Item's width, not
190the \l Rectangle's width. To bind the \l Rectangle's \c height to its own \c width,
191the binding expression must explicitly refer to \c this.width (or alternatively,
205 Component.onCompleted: {
206 rect.height = Qt.binding(function() { return this.width * 2 })
207 console.log("rect.height = " + rect.height) // prints 200, not 1000
212\note The value of \c this is not defined outside of property bindings.
213See \l {JavaScript Environment Restrictions} for details.