ercishli
ercishli

Reputation: 25

How to dynamically update a child ListModel within a singleton?

I try to understand how shared qml objects can be used globally by other qml and javascript files. I have a QML app that has two comboboxes in one window. One is parent (country) combo box in ApplicationWindow, other one is child (city) combo box in Page1.qml. When selecting a country, the child combo box should have cities of the country at the same time. This is possible when using the comboboxes and the function are in ApplicationWindow, I had asked a question about it here. With the help of the answer of my previous question I tried to connect child combobox outside of ApplicationWindow to parent combobox in ApplicationWindow using qmldir, singleton and javascript. I tried child combobox's list model to be a singleton object, it doesn't work and it gives error qrc:/script.js:11: Error: Cannot assign QJSValue to QQmlListModel*

main.qml:

import QtQuick 2.11
import QtQuick.Window 2.11
import QtQuick.Controls 2.4
import QtQuick.Layouts 1.3
import Qt.labs.settings 1.0
import "script.js" as JS
ApplicationWindow {
    visible: true
    width: 640
    height: 480
    title: qsTr("Hello World")
    property int currentindex: comboBox2.currentIndex
    Settings{
        property alias country : comboBox2.currentIndex
    }
    Dialog {
        id: dialog
        title: "Select Country"
        implicitWidth: parent.width
        implicitHeight: parent.height/2
        Column{
        ComboBox {
            id: comboBox2
            x: 199
            y: 176
            width: 277
            height: 48
            currentIndex: 0
            model:
             ListModel {
             ListElement { text: qsTr("USA") }
             ListElement { text: qsTr("Russia") }
             ListElement { text: qsTr("Iran") }
            }
            onCurrentIndexChanged:{
                currentindex = currentIndex
                JS.coord_combo_changed()
            }
        }
        }
    }
    ColumnLayout{
        anchors.horizontalCenter: parent.horizontalCenter
        spacing:20
        width: parent.width
    Button{
        anchors.horizontalCenter: parent.horizontalCenter
        id:select_country
        text:"select country"
        onClicked: dialog.open()
    }
    Page1{
        anchors.horizontalCenter: parent.horizontalCenter
    }
    }
}

Page1.qml:

import QtQuick 2.11
import QtQuick.Controls 2.4
import QtQuick.Layouts 1.3
Page{
    RowLayout{
        anchors.horizontalCenter: parent.horizontalCenter
        spacing:5
        width: parent.width
   Text{
            text:"Select City: "
        }
   ChildCombo{
   id:comboBox1
   model: Shared.childmodel
   }
    }
}

qmldir:

singleton Shared 1.0 Shared.qml

Shared.qml:

pragma Singleton
import QtQuick 2.9
import QtQuick.Controls 2.2
QtObject {
    property ListModel childmodel: ChildModel{}
}

ChildModel.qml:

import QtQuick 2.0
ListModel {}

script.js:

function coord_combo_changed(){
    if(currentindex === 0){
        Shared.childmodel = ["New York", "Washington", "Houston"]
    return Shared.childmodel
}
else if (currentindex === 1){
    Shared.childmodel = ["Moscow","Saint Petersburg","Novosibirsk"]
    return Shared.childmodel
}
else if (currentindex === 2){
    Shared.childmodel = ["Tehran","Tabriz","Shiraz"]
    return Shared.childmodel
}
}

I also tried to make combobox as a shared object, it also didn't work and it didn't give any error either. Is it possible to update the child combo box?

Thank you.

Upvotes: 1

Views: 641

Answers (1)

eyllanesc
eyllanesc

Reputation: 244301

In QML a model can be a list, a ListModel, a QAbstractItemModel, etc., but those objects are not equivalent. And that is your mistake, you are trying to point out that a ListModel is a list, in this case the solution is to first clean the model and then add the elements with the append method:

function coord_combo_changed(){
    var values = [];
    if(currentindex === 0){
        values = ["New York", "Washington", "Houston"]
    }
    else if (currentindex === 1){
        values = ["Moscow","Saint Petersburg","Novosibirsk"]
    }
    else if (currentindex === 2){
        values = ["Tehran","Tabriz","Shiraz"]
    }
    Shared.childmodel.clear()
    for(var i in values){
        Shared.childmodel.append({"text": values[i]});
    }
}

On the other hand I see that your code throws warning indicating that you should not use the anchors if the items are within a layout, in your case you should change to:

ColumnLayout{
    anchors.horizontalCenter: parent.horizontalCenter
    spacing:20
    width: parent.width
    Button{
        Layout.alignment: Qt.AlignHCenter // <---
        id:select_country
        text:"select country"
        onClicked: dialog.open()
    }
    Page1{
        Layout.alignment: Qt.AlignHCenter // <---
    }
}

Upvotes: 0

Related Questions