Can't edit object properties in QML javascript file

584 Views Asked by At

Can someone please explain to me what I am doing wrong with the following setup.

The idea is to develop the game engine in engine.js and the UI logic is in the qml file.

page.qml

Page {
    id: page
    SilicaGridView {
        id: listView
        model: ListModel {
            id: roleList
            Component.onCompleted: {
                Engine.addRoles(roleList);
            }
        }

        delegate: Rectangle {
            id: delegate
            border.color: model.selected ? Theme.highlightColor : Theme.primaryColor

            Label {
                text: qsTr(model.name)
            }
            MouseArea {
                anchors.fill: parent;
                onClicked: {
                    Engine.selectRole(model);
                }
            }
        }
    }
}

engine.js:

function Role() {
    this.name = "role"
    this.selected = false;
}

function addRoles(list) {
    list.append(new Role());
    list.append(new Role());
}

function selectRole(role) {
    console.log(role.selected) // <-- false
    role.selected = true;
    console.log(role.selected) // <-- false
}

So when I click an element on the page, it calls selectRole from the engine. For some weird reason updating the selected property on the model does not actually update the model. Why is it like this?

1

There are 1 best solutions below

1
On

Views in Qt Quick already have a method of keeping track of the selected item:

That means you don't need to have a selected variable in your Role objects. Engine.js becomes:

function Role() {
    this.name = "role"
}

function addRoles(list) {
    list.append(new Role());
    list.append(new Role());
}

Your QML code doesn't run (it really helps if you provide a working example), so I took the liberty of making it run:

import QtQuick 2.3
import QtQuick.Controls 1.1

import "Engine.js" as Engine

ApplicationWindow {
    width: 500
    height: 500

    ListView {
        id: listView
        width: 100
        height: 100
        anchors.centerIn: parent

        model: ListModel {
            id: roleList
            Component.onCompleted: {
                Engine.addRoles(roleList);
            }
        }

        delegate: Rectangle {
            id: delegateItem
            border.color: ListView.isCurrentItem ? "red" : "black"
            width: listView.width
            height: 30

            Label {
                id: label
                text: qsTr(model.name)
                anchors.centerIn: parent
            }
            MouseArea {
                anchors.fill: parent;
                onClicked: {
                    listView.currentIndex = index;
                    print(index, delegateItem.ListView.isCurrentItem)
                }
            }
        }
    }
}

Notice the use of ListView's attached property isCurrentItem. That's a convenience property that is equivalent to:

delegate: Rectangle {
    border.color: listView.currentIndex == index ? "red" : "black"
}