qtqmlqtquick2qtquickcontrols2

How to bind an optional property in QML?


I'm developping a QtQuick Custom Style (according too this documentation), and I'm facing a problem.

My Button template implementation expose an additionnal user property

MyCustomStyle/Button.qml

import QtQuick
import QtQuick.Controls
import QtQuick.Templates as T

T.Button {
    id: control

    enum ButtonVariations {
        Giant,
        Regular,
        Small
    }

    property int variation : Button.ButtonVariations.Regular

    //...
}

The problem is that when I use a Button in my application, it will load either this Button template definition, or another one, depending on the style choosen for the app. This result in an error in qml

MyApp/SomePage.qml

    ComboBox {
        id: comboBox
        width: 140
        height: 25

        model: ["Giant", "Regular", "Small"]
    }

    Button {
        Layout.alignment: Qt.AlignRight | Qt.AlignTop
        text: "Normal"
        implicitWidth: 100

        variation : comboBox.currentIndex    //error : Invalid property name "variation" (M16)
    }

When I run the app, it works great, and the button reacts according to the property. But due to this error, Qt Design Studio cannot parse the file, and cannot adapt views.


Question : Is it possible to assign this property as an "optionnal" property in QML ?


I've already tried this, unsuccesfully :

1 - Check if property exists (according to this topic)

    variation ? variation : comboBox.currentIndex //Do not works

-> this syntax doesn't seems to exists

2 - Re-declare property in the instantiation (so it could overrides or first-declare the property)

Button {
    id: myButton

    property int variation : comboBox.currentIndex //Do not works
}

-> This compile and doesn't generate error, but it's like if the property inside the T.Button isn't binded anymore. Nothing reacts

EDIT : 3 - Try to use a simple Binding type as follow (thanks to smr's comment)

Binding {
    variation: comboBox.currentIndex
}

-> Generate an error at runtime. Component cannot be loaded


Solution

  • I'm currently unable to reproduce the exact condition because the problem occurs in Qt Design Studio. What I've tried is removing the defined variable (by commenting it out) to make it work.

    Meanwhile, @iam_peter has suggested a method of initializing the property inside Component.onCompleted.
    Also, there's an alternative approach using Binding; when you need to initialize a component in a delayed mode or when a specific condition is met.

    Since Qt 6.*, there are three ways to use Binding, but in two of these methods, the variable must exist at parse time, and one is checked at runtime.

    Currently, I'm unsure how to reproduce a condition where the component has the property at parse time but not at runtime.

    * Based on this, I think that if Binding { when: button.variation !== undefined; button.variation: comboBox.currentIndex } works, then Binding { button.variation: comboBox.currentIndex } should also work.

    The following is the code that I have tried:

    component Button: T.Button {
        // property int variation: 0
        text: "Text " + (this.variation ?? "")
    }
    
    Row {   
        Button { 
            // Run-time checking, no Error
            id: button1
            Binding {
                when: Object(button1).hasOwnProperty('variation')
                target: button1; property: 'variation'; value: 1
            }
        }
    
        Button { 
            // Parse-time checking
            // Error, if `variation` is not defined while parsing the file.
            id: button2
            Binding on variation {
                value: 2
                when: Object(button2).hasOwnProperty('variation')
            }
        }
    
        Button { 
            // Parse-time checking
            // Error, if `variation` is not defined while parsing the file.
            id: button3
            Binding {
                target: button3; property: 'variation'; value: 3
                when: Object(button3).hasOwnProperty('variation')
            }
        }
    }