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. Defining a function in ListElement - Not working with append
Forum Updated to NodeBB v4.3 + New Features

Defining a function in ListElement - Not working with append

Scheduled Pinned Locked Moved Unsolved QML and Qt Quick
3 Posts 3 Posters 1.2k Views 2 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.
  • B Offline
    B Offline
    bkeller
    wrote on 24 Jun 2020, 07:36 last edited by
    #1

    Hi all,

    I want to assign a function declaration to a role in a ListElement in a ListModel. I understand from the docs that this has been allowed since 5.11. "Beginning with Qt 5.11 ListElement also allows assigning a function declaration to a role. This allows the definition of ListElements with callable actions." - ListElement QML Type

    Searching around I found a few places where people were having issues with this, including:
    https://stackoverflow.com/questions/50622945/calling-javascript-object-method-from-qml-listview-delegate/
    https://bugreports.qt.io/browse/QTBUG-80041
    https://forum.qt.io/topic/95918/problem-dynamically-adding-items-in-a-listmodel

    My current findings are:

    1. Defining function as a role inside a ListElement declaration works
    2. Defining function inside JS object that is appended to ListModel, does not work
    3. From this forum post, adding function as a role to existing ListElement by using setProperty works

    Here is some sample code (portions borrowed from links above) that tries to illustrate the scenarios. Item 1 and Item 3 work. Item 2/Scenario 2 gets the following error: Can't assign to existing role 'func' of different type [VariantMap -> Function].

    If you comment out the first and third ListElement declarations, this error doesn't happen. But the typeof model.func == object and not function. And I'm not sure if there's a way to invoke the function or define it differently so that it would be invocable.

    Any thoughts?

    import QtQuick 2.14
    import QtQuick.Controls 2.14
    
    ApplicationWindow {
        visible: true
        width: 640
        height: 480
        title: qsTr("TestListElement")
    
        ListView {
            id: myListView
            anchors.fill: parent
            spacing: 2
            model: ListModel {
                id: myListModel
                ListElement {
                    name: "Item 1"
                    func: function(){ console.log("Item 1 clicked"); }
                }
            }
            Component.onCompleted: {
                myListModel.append({ name: "Item 2", func: function (){ console.log("Item 2 clicked");} });
    
                myListModel.append({ name: "Item 3"});
                myListModel.setProperty(myListModel.count-1, "func", function (){ console.log("Item 3 clicked");});
            }
    
    
            delegate: Rectangle {
                height: 30
                color: "#EFEFEF"
                border { width: 1; color: "#CCC" }
                width: parent.width
                Text {
                    text: name
                    anchors.centerIn: parent
                }
                MouseArea {
                    anchors.fill: parent
                    onClicked: {
                        if(typeof model.func === "function")
                            model.func();
                        else
                            console.error("Click handler not defined. Func typeof == " + typeof model.func);
                    }
                }
            }
        }
    }
    
    S 1 Reply Last reply 20 Mar 2021, 23:52
    1
    • B bkeller
      24 Jun 2020, 07:36

      Hi all,

      I want to assign a function declaration to a role in a ListElement in a ListModel. I understand from the docs that this has been allowed since 5.11. "Beginning with Qt 5.11 ListElement also allows assigning a function declaration to a role. This allows the definition of ListElements with callable actions." - ListElement QML Type

      Searching around I found a few places where people were having issues with this, including:
      https://stackoverflow.com/questions/50622945/calling-javascript-object-method-from-qml-listview-delegate/
      https://bugreports.qt.io/browse/QTBUG-80041
      https://forum.qt.io/topic/95918/problem-dynamically-adding-items-in-a-listmodel

      My current findings are:

      1. Defining function as a role inside a ListElement declaration works
      2. Defining function inside JS object that is appended to ListModel, does not work
      3. From this forum post, adding function as a role to existing ListElement by using setProperty works

      Here is some sample code (portions borrowed from links above) that tries to illustrate the scenarios. Item 1 and Item 3 work. Item 2/Scenario 2 gets the following error: Can't assign to existing role 'func' of different type [VariantMap -> Function].

      If you comment out the first and third ListElement declarations, this error doesn't happen. But the typeof model.func == object and not function. And I'm not sure if there's a way to invoke the function or define it differently so that it would be invocable.

      Any thoughts?

      import QtQuick 2.14
      import QtQuick.Controls 2.14
      
      ApplicationWindow {
          visible: true
          width: 640
          height: 480
          title: qsTr("TestListElement")
      
          ListView {
              id: myListView
              anchors.fill: parent
              spacing: 2
              model: ListModel {
                  id: myListModel
                  ListElement {
                      name: "Item 1"
                      func: function(){ console.log("Item 1 clicked"); }
                  }
              }
              Component.onCompleted: {
                  myListModel.append({ name: "Item 2", func: function (){ console.log("Item 2 clicked");} });
      
                  myListModel.append({ name: "Item 3"});
                  myListModel.setProperty(myListModel.count-1, "func", function (){ console.log("Item 3 clicked");});
              }
      
      
              delegate: Rectangle {
                  height: 30
                  color: "#EFEFEF"
                  border { width: 1; color: "#CCC" }
                  width: parent.width
                  Text {
                      text: name
                      anchors.centerIn: parent
                  }
                  MouseArea {
                      anchors.fill: parent
                      onClicked: {
                          if(typeof model.func === "function")
                              model.func();
                          else
                              console.error("Click handler not defined. Func typeof == " + typeof model.func);
                      }
                  }
              }
          }
      }
      
      S Offline
      S Offline
      Swerved
      wrote on 20 Mar 2021, 23:52 last edited by
      #2

      @bkeller came here looking for a example of a function declaration in a ListElement, so thanks for that.

      Haven’t tried the code but reviewing it, here’s my suggestion.

      I would suggest the answer to this topic that function declarations can only be made in a ListElement when it’s initialised in a model and not dynamically as your code suggests.

      Therefore the probably solution is a functionid element holding an integer or enumeration, and use a switch function to execute the code you are after.

      1 Reply Last reply
      0
      • A Offline
        A Offline
        Ankalagon
        wrote on 14 Dec 2022, 20:55 last edited by Ankalagon
        #3

        In case someone is looking for this, my approach is the following:

        ListModel {
                    id: buttons
                    ListElement {
                        title: "Test Button"
                        onButtonClicked: function(value) {
                            console.log("clicked", value)
                        }
                    }
                }
        
        ListView {
                    id: buttonListView
                    width: 100
                    height: 500
                    model: buttons
                    delegate: Button {
                        text: title
                        width: buttonListView.width
                        height: 50
                        onClicked: onButtonClicked(title)
                    }
                }
        

        Important in this case is that onButtonClicked begins with function(value), only function() did not work for me.

        1 Reply Last reply
        0

        • Login

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