Alexey Andronov
Alexey Andronov

Reputation: 602

How to listen for property collection size changes

I want to automatically show/hide view depending on a property's collection size, here's the code:

QtObject {
    property var controlWindow: Window {
        property var collection: []

        signal sigAddElement(var element)
        onSigAddElement: {
            collection.push(element)
        }

        signal sigEraseAllElements()
        onSigEraseAllElements: {
            collection.length = 0
        }

        onCollectionChanged: {
            console.log("collection.len = " + collection.length)
        }

        Rectangle {
            id: autoHidableView
            visible: collection.length != 0
        }
    }
}

but visible property of autoHidableView evaluates only once on startup and never evaluates again
The onCollectionChanged handler is never get called which is understandable since collection object itself stays the same
So is it possible to listen for collection's size change event?

Upvotes: 0

Views: 211

Answers (2)

Amfasis
Amfasis

Reputation: 4198

The problem is that the javascript array that you create with property var collection: [] does not have any signals (the onCollectionChanged is indeed when you would assign a new collection to it). You better use ListModel:

QtObject {
    property var controlWindow: Window {

        ListModel {
            id: collection
        }

        signal sigAddElement(var element)
        onSigAddElement: {
            collection.append(element)
        }

        signal sigEraseAllElements()
        onSigEraseAllElements: {
            collection.clear()
        }

        Rectangle {
            id: autoHidableView
            visible: collection.count > 0
        }
    }
}

Note that you need to change the push to append

Upvotes: 1

augre
augre

Reputation: 2051

Listening to the array length is not enough. See var QML Basic Type:

It is important to note that changes in regular properties of JavaScript objects assigned to a var property will not trigger updates of bindings that access them.

It is the same behavior when assigning an array to the var. The binding will only be reevaluated if the property is reassigned with an entire new object/array.

You have 2 ways to make your binding listen to the collection length change:

  • Reassign the entire array:

    onSigAddElement: {
        collection = collection.concat(element)
    }
    // ...
    onSigEraseAllElements: {
        collection = []
    }
    
  • Trigger the change signal manually:

    onSigAddElement: {
        collection.push(element)
        collectionChanged()
    }
    // ...
    onSigEraseAllElements: {
        collection.length = 0
        collectionChanged()
    }
    

Upvotes: 1

Related Questions