Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. QML and Qt Quick
  4. QML: Functions inside var-array model become undefined after switching Repeater model
Forum Updated to NodeBB v4.3 + New Features

QML: Functions inside var-array model become undefined after switching Repeater model

Scheduled Pinned Locked Moved Solved QML and Qt Quick
5 Posts 3 Posters 260 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • T Offline
    T Offline
    timafaer
    wrote on last edited by
    #1

    Title:

    QML: JS functions in var-array model disappear when switching models in Repeater


    Post:

    I'm running into a strange issue in QML when using a Repeater with a JavaScript array model that contains objects with function properties.

    When the Repeater uses a plain JavaScript array (property var), the functions are preserved and callable from the delegate.
    But when I switch the model to another one (even another property var array), or mix it with a ListModel, the function properties become undefined inside the delegate.


    Expected behavior

    modelData.handler should remain a valid JavaScript function inside the delegate, as long as the model contains JS objects with function members.


    Actual behavior

    Inside the delegate:

    console.log(typeof modelData.handler)
    

    prints:

    undefined
    

    The same model works correctly when used directly, but breaks when assigned dynamically using an expression like:

    model: condition ? actionsModel : defaultActionsModel
    

    Minimal reproducible example

    main.qml

    import QtQuick 2.15
    
    Item {
        id: root
        width: 400
        height: 200
    
        // Works when used alone
        property var actionsModel: [
            {
                title: "Action A",
                handler: function() { console.log("A run") }
            }
        ]
    
        // Switching to this causes functions to disappear
        property var defaultActionsModel: [
            {
                title: "Default",
                handler: function() { console.log("Default run") }
            }
        ]
    
        property bool useDefault: false
    
        Repeater {
            id: rep
            model: root.useDefault ? root.defaultActionsModel : root.actionsModel
    
            delegate: Rectangle {
                width: 120; height: 40; color: "lightgray"
    
                MouseArea {
                    anchors.fill: parent
                    onClicked: {
                        console.log("typeof handler:", typeof modelData.handler)
                        if (modelData.handler)
                            modelData.handler()
                    }
                }
            }
        }
    
        Timer {
            running: true; interval: 1500; repeat: false
            onTriggered: root.useDefault = true
        }
    }
    

    After the model switches, typeof modelData.handler becomes "undefined".


    What I have tried

    • Using index instead of modelData → same result
    • Removing bindings and animations → no effect
    • Ensuring both models are property var JS arrays (not ListModel)
    • If I never switch the model, functions always work

    Environment

    • Qt 5.15.2 (also tested on 5.12 and 6.2)
    • Windows 10
    • qmake build, Release

    Question

    Is this a known limitation of how QML handles dynamic model assignment?
    Why does switching between two JS array models cause function properties to become undefined inside the delegate?

    Is there a reliable way to use JS functions inside model objects when the model is selected dynamically?


    Additional note:
    I’ve already gone through several potential explanations (including those
    suggested by AI tools), but none of them addressed the actual underlying
    issue.

    Therefore, I’m specifically looking for an answer grounded in QML internals
    or model handling mechanisms, rather than speculative suggestions.

    1 Reply Last reply
    0
    • T Offline
      T Offline
      timafaer
      wrote last edited by timafaer
      #3

      In QML, the model of a Repeater is always treated as an item model (conceptually similar to a ListModel).
      Even when you pass a plain JavaScript array (property var), QML internally wraps it into a list model so that the delegate can access rows via index, modelData, roles, etc.

      A ListModel (and the internal list model used by Repeater) can only store values that are representable as QVariants: numbers, strings, booleans, simple JS objects, etc.
      JavaScript functions are not supported as model data, so when the array is wrapped into this internal model, any function properties are effectively lost or become non-callable. That’s why inside the delegate typeof modelData.handler (or modelData[1]) is no longer "function".

      B JKSHJ 2 Replies Last reply
      0
      • JKSHJ Offline
        JKSHJ Offline
        JKSH
        Moderators
        wrote on last edited by
        #2

        Hi @timafaer, your code works as expected for me on Qt 6.5, 6.8, and 6.10. I'm guessing that it was a bug that has now been fixed.

        Qt 5 and 6.2 have reached end-of-life. Please upgrade.

        Qt Doc Search for browsers: forum.qt.io/topic/35616/web-browser-extension-for-improved-doc-searches

        1 Reply Last reply
        0
        • T Offline
          T Offline
          timafaer
          wrote last edited by timafaer
          #3

          In QML, the model of a Repeater is always treated as an item model (conceptually similar to a ListModel).
          Even when you pass a plain JavaScript array (property var), QML internally wraps it into a list model so that the delegate can access rows via index, modelData, roles, etc.

          A ListModel (and the internal list model used by Repeater) can only store values that are representable as QVariants: numbers, strings, booleans, simple JS objects, etc.
          JavaScript functions are not supported as model data, so when the array is wrapped into this internal model, any function properties are effectively lost or become non-callable. That’s why inside the delegate typeof modelData.handler (or modelData[1]) is no longer "function".

          B JKSHJ 2 Replies Last reply
          0
          • T timafaer has marked this topic as solved
          • T timafaer

            In QML, the model of a Repeater is always treated as an item model (conceptually similar to a ListModel).
            Even when you pass a plain JavaScript array (property var), QML internally wraps it into a list model so that the delegate can access rows via index, modelData, roles, etc.

            A ListModel (and the internal list model used by Repeater) can only store values that are representable as QVariants: numbers, strings, booleans, simple JS objects, etc.
            JavaScript functions are not supported as model data, so when the array is wrapped into this internal model, any function properties are effectively lost or become non-callable. That’s why inside the delegate typeof modelData.handler (or modelData[1]) is no longer "function".

            B Online
            B Online
            Bob64
            wrote last edited by Bob64
            #4

            @timafaer

            I was aware of the issue with ListModel as I have encountered this myself but I didn't know it applied to a raw JS array model, so that is interesting to know. Thanks for your update.

            When I encountered the issue using ListModel (I wanted a field in the model to hold a function), I worked around it by moving the model data into a JS array and programmatically creating the ListModel from it. The raw array still held the functions but I skipped these when adding the data to the model. Instead, when I needed to access a function in a delegate, I used the index to index back into the JS array.

            I guess another approach that might work for you, which would avoid introducing the ListModel, is simply having two parallel arrays one of which you use as the model and the other to hold the functions. You could use the same indexing approach with this. (In my case, there were other reasons why it was convenient to have a ListModel.)

            1 Reply Last reply
            1
            • T timafaer

              In QML, the model of a Repeater is always treated as an item model (conceptually similar to a ListModel).
              Even when you pass a plain JavaScript array (property var), QML internally wraps it into a list model so that the delegate can access rows via index, modelData, roles, etc.

              A ListModel (and the internal list model used by Repeater) can only store values that are representable as QVariants: numbers, strings, booleans, simple JS objects, etc.
              JavaScript functions are not supported as model data, so when the array is wrapped into this internal model, any function properties are effectively lost or become non-callable. That’s why inside the delegate typeof modelData.handler (or modelData[1]) is no longer "function".

              JKSHJ Offline
              JKSHJ Offline
              JKSH
              Moderators
              wrote last edited by
              #5

              @timafaer said in QML: Functions inside var-array model become undefined after switching Repeater model:

              JavaScript functions are not supported as model data, so when the array is wrapped into this internal model, any function properties are effectively lost or become non-callable. That’s why inside the delegate typeof modelData.handler (or modelData[1]) is no longer "function".

              That was the case in Qt 5.15, but that's no longer true in Qt 6.5+. As I mentioned before, your code works just fine with a recent version of Qt.

              Qt Doc Search for browsers: forum.qt.io/topic/35616/web-browser-extension-for-improved-doc-searches

              1 Reply Last reply
              3

              • Login

              • Login or register to search.
              • First post
                Last post
              0
              • Categories
              • Recent
              • Tags
              • Popular
              • Users
              • Groups
              • Search
              • Get Qt Extensions
              • Unsolved