Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-90356

Pushing function as property to StackView doesn't result in that property being set

    XMLWordPrintable

    Details

      Description

      I have a component that allows a property to be overridden with a custom function. The idea is that it sets a function by default for convenience, but allows you to set your own:

      import QtQuick 2.12
      import QtQuick.Controls 2.12
      
      ApplicationWindow {
          width: 640
          height: 480
          visible: true
          title: qsTr("Hello World")
      
          Component {
              id: mainMenuComponent
      
              Button {
                  text: "Load game"
                  onClicked: StackView.view.push(loadGamePage, {
                      contextualActionHandler: function(saveIndex, saveUrl, saveName) {
                         print("correct handler called")
                      }
                  })
              }
          }
      
          Component {
              id: loadGamePage
      
              Item {
                  property alias contextualActionHandler: listView.contextualActionHandler
      
                  Button {
                      id: listView
                      text: "Load this specific saved game"
      
                      property var contextualActionHandler: function(saveIndex, saveUrl, saveName) {
                          print("default contextual action handler called")
                      }
      
                      onClicked: contextualActionHandler(0, "foo.json", "foo")
                  }
              }
          }
      
          StackView {
              objectName: "mainStackView"
              initialItem: mainMenuComponent
              anchors.fill: parent
          }
      }
      

      The issue is that the function I pass in is not set. To reproduce the issue:

      • Click on "Load game".
      • Click on "Load this specific saved game"; "correct handler called" should be printed, but instead the default message is.

      Trying something similar with inline components and no StackView works:

      import QtQuick 2.15
      import QtQuick.Controls 2.15
      
      ApplicationWindow {
          width: 640
          height: 480
          visible: true
          title: qsTr("Hello World")
      
          component LoadGamePage: Item {
              property alias contextualActionHandler: listView.contextualActionHandler
      
              Button {
                  id: listView
                  text: "Load this specific saved game"
      
                  property var contextualActionHandler: function(saveIndex, saveUrl, saveName) {
                      print("default contextual action handler called")
                  }
      
                  onClicked: contextualActionHandler(0, "foo.json", "foo")
              }
          }
      
          LoadGamePage {
              contextualActionHandler: function(saveIndex, saveUrl, saveName) {
                 print("correct handler called")
              }
          }
      }
      

      I had a look around trying to find similar bugs, but the closest I found was QTBUG-56125, which doesn't look related, but surprisingly using a binding does work:

      import QtQuick 2.12
      import QtQuick.Controls 2.12
      
      ApplicationWindow {
          width: 640
          height: 480
          visible: true
          title: qsTr("Hello World")
      
          Component {
              id: mainMenuComponent
      
              Button {
                  text: "Load game"
                  onClicked: StackView.view.push(loadGamePage, {
                      contextualActionHandler: Qt.binding(function() {
                          return function(saveIndex, saveUrl, saveName){ print("correct handler called") }
                      })
                  })
              }
          }
      
          Component {
              id: loadGamePage
      
              Item {
                  property alias contextualActionHandler: listView.contextualActionHandler
      
                  Button {
                      id: listView
                      text: "Load this specific saved game"
      
                      property var contextualActionHandler: function(saveIndex, saveUrl, saveName) {
                          print("default contextual action handler called")
                      }
      
                      onClicked: contextualActionHandler(0, "foo.json", "foo")
                  }
              }
          }
      
          StackView {
              objectName: "mainStackView"
              initialItem: mainMenuComponent
              anchors.fill: parent
          }
      }
      

      I don't think using a binding in this case should be necessary.

        Attachments

          Issue Links

          No reviews matched the request. Check your Options in the drop-down menu of this sections header.

            Activity

              People

              Assignee:
              qt.team.quick.subscriptions Qt Quick and Widgets Team
              Reporter:
              mitch_curtis Mitch Curtis
              Votes:
              0 Vote for this issue
              Watchers:
              3 Start watching this issue

                Dates

                Created:
                Updated:
                Resolved:

                  Gerrit Reviews

                  There are no open Gerrit changes