This is a text-only version of the following page on https://raymii.org: --- Title : Qt/QML Property bindings break after a JavaScript assignment Author : Remy van Elst Date : 19-05-2022 05:30 URL : https://raymii.org/s/articles/Qt_QML_Property_bindings_break_after_javascript_assignment.html Format : Markdown/HTML --- Property bindings are one of the most powerful concepts in Qt/QML. Property bindings let you specify relationships between different object properties. When a properties dependencies change in value, the property is automatically updated according to the specified relationship. The QML engine monitors the properties dependencies (that is, the variables in the binding expression). When a change is detected, the QML engine re-evaluates the binding expression and applies the new result to the property. One little known caveat with property bindings is that they break after a static JavaScript assignment (`property = value`). This post shows you the different behaviors and how to use `Qt.binding()` to assign property bindings via JavaScript. <p class="ad"> <b>Recently I removed all Google Ads from this site due to their invasive tracking, as well as Google Analytics. Please, if you found this content useful, consider a small donation using any of the options below:</b><br><br> <a href="https://leafnode.nl">I'm developing an open source monitoring app called Leaf Node Monitoring, for windows, linux & android. Go check it out!</a><br><br> <a href="https://github.com/sponsors/RaymiiOrg/">Consider sponsoring me on Github. It means the world to me if you show your appreciation and you'll help pay the server costs.</a><br><br> <a href="https://www.digitalocean.com/?refcode=7435ae6b8212">You can also sponsor me by getting a Digital Ocean VPS. With this referral link you'll get $100 credit for 60 days. </a><br><br> </p> Do note that this behavior is intended, [documented][2] and can be useful in situations where you want to purposely want to break a property binding. This post is intended to inform you of the different behaviors, as it can be confusing if you're unaware of what is happening. A colleague of mine was working on a bug, he was not aware of this behavior and it cost him two hours to figure out that it was the underlying issue. Could happen to me as well when you're knee-deep into a debugging session. ### Demonstration ![demo][1] The image above demonstrates the issue. The top `Button` (`id: boundButton`) `text` property is bound to the `TextField` (`id: bindableTextField`) `text` property, so when you edit the text, the text on the button updates automatically. The second button breaks the binding by doing a JavaScript assignment in it's `onClicked` function: onClicked: boundButton.text = "Binding broken" If you've clicked the button and then change the text in the `TextField`, the button's text no longer reflects the text you've typed. The last button restores the property binding using the `Qt.binding()` function: onClicked: boundButton.text = Qt.binding(function () { return bindableTextField.text }) } A bit convoluted syntax wise, but it gets the job done. ### Qt.binding() The [documentation][3] states the following: > Returns a JavaScript object representing a property binding, with a function that evaluates the binding. There are two main use-cases for the function: firstly, to apply a property binding imperatively from JavaScript code and secondly, to apply a property binding when initializing property values of dynamically constructed objects (via `Component.createObject()` or `Loader.setSource()`). Confusingly, that page has examples for the second use case, not the first. Simpler examples are on [the other doc page][2], transcribed below: The Rectangle below initially ensures that its height is always twice its `width`. However, when the space key is pressed, the current value of `width*3` will be **assigned to height as a static value**. After that, the height will remain fixed at this value, even if the width changes. The assignment of the static value removes the binding. Rectangle { width: 100 height: width * 2 focus: true Keys.onSpacePressed: { height = width * 3 } } If the intention is to give the rectangle a fixed height and stop automatic updates, then this is not a problem. However, if the intention is to establish a new relationship between width and height, then the new binding expression must be wrapped in the `Qt.binding()` function instead: Rectangle { width: 100 height: width * 2 focus: true Keys.onSpacePressed: { height = Qt.binding(function() { return width * 3 }) } } Now, after the space key is pressed, the rectangle's height will continue auto-updating to always be three times its width. --- The other use case is, in my experience, not used often, or at least not in the projects I've worked on. Dynamically creating QML objects is fun at first, but you loose type safety and it's all strings, so changing one name will work fine at first, until you get runtime errors somewhere else. Maybe I'm spoiled by the compile-time safety, but such a small typo or rename has caught me more than I'd like to admit. Whereas, in C++ it'll just won't compile anymore. [1]: /s/inc/img/qt-binding.gif [2]: https://web.archive.org/web/20220516083722/https://doc.qt.io/qt-5/qtqml-syntax-propertybinding.html [3]: https://web.archive.org/web/20220516084540/https://doc.qt.io/qt-5/qml-qtqml-qt.html#binding-method --- License: All the text on this website is free as in freedom unless stated otherwise. This means you can use it in any way you want, you can copy it, change it the way you like and republish it, as long as you release the (modified) content under the same license to give others the same freedoms you've got and place my name and a link to this site with the article as source. This site uses Google Analytics for statistics and Google Adwords for advertisements. You are tracked and Google knows everything about you. Use an adblocker like ublock-origin if you don't want it. All the code on this website is licensed under the GNU GPL v3 license unless already licensed under a license which does not allows this form of licensing or if another license is stated on that page / in that software: This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. Just to be clear, the information on this website is for meant for educational purposes and you use it at your own risk. I do not take responsibility if you screw something up. Use common sense, do not 'rm -rf /' as root for example. If you have any questions then do not hesitate to contact me. See https://raymii.org/s/static/About.html for details.