[SOLVED] QML Nested ListModel For ComboBox

Issue

I want to use comboBox which it’s model is taken from a nested model.

The simplified Code:

main.qml:

import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.15

ApplicationWindow {
    id: applicationWindow

    width: 300
    height: 200
    visible: true
    title: qsTr("01_Change_Model_Data")

    ListModel {
        id: listModel1
        ListElement {
            labelText: "ComboBox 1:"

            //subItems: ["First", "Second", "Third"]
            subItems: [
                ListElement {text: "First"},
                ListElement {text: "Second"},
                ListElement {text: "Third"}
            ]

        }
        ListElement {
            labelText: "ComboBox 2:"

            //subItems: ["First", "Second", "Third"]
            subItems: [
                ListElement {text: "First"},
                ListElement {text: "Second"},
                ListElement {text: "Third"}
            ]

        }
    }


    Button {
        id: loadUnloadBtn
        height: 24
        width: 50
        text: "Load"

        anchors {
            right: parent.right
            rightMargin: 20
            top: parent.top
            topMargin: 10
        }
        onClicked: {
            if(comboBoxAreaLoader.source == "") {
                comboBoxAreaLoader.source = "ComboBoxArea.qml"
            }else {
                comboBoxAreaLoader.source = ""
            }

        }
    }

    Loader {
        id: comboBoxAreaLoader
        anchors {
            top: parent.top
            topMargin: 10
            bottom: parent.bottom
            bottomMargin: 10
            left: parent.left
            leftMargin: 10
            right: parent.right
            rightMargin: 80
        }
        source: ""
        property variant comboBoxModel: subItems
        onStatusChanged: if(status == Loader.Ready) comboBoxModelAlias = comboBoxModel
    }
}

ComboBoxArea.qml:

import QtQuick 2.15
import QtQuick.Controls 2.15


Item {
    id: listViewDelegate
    ListView {
        id: listView1
        anchors.fill: parent

        model: listModel1
        delegate: listElementDelegate
        spacing: 6
    }

    Component {
        id: listElementDelegate
        Rectangle {
            id: delegateRectangleRoot

            property alias comboBoxModelAlias: comboBox.model

            height: 30
            width: 200
            Label {
                id: comboBoxNameLabel
                color: "red"
                width: 80
                height: 30
                anchors {
                    left: parent.left
                    leftMargin: 10
                }
                text: labelText
                verticalAlignment: Text.AlignVCenter
            }

            ComboBox {
                id: comboBox
                height: 30
                width: 100
                //model: ["First", "Second", "Third"]

                anchors {
                    left: comboBoxNameLabel.right
                    leftMargin: 10
                    verticalCenter: comboBoxNameLabel.verticalCenter
                }
            }

        }

    }
}

I think main problem is defining subItems in nested list. First, I tried to declare it as js list like:

subItems: ["First", "Second", "Third"]

But I got an error:

ListElement: cannot use script for property value

Then I tried to change it with listElements:

subitems: [
    ListElement {text: "First"},
    ListElement {text: "Second"},
    ListElement {text: "Third"}
]

This time I got two errors:

ReferenceError: subItems is not defined

Error: Invalid write to global property "comboBoxModelAlias"

Actually I’m confused. Do you have any idea what I am doing wrong?

Application window screenshot

Solution

I think you were just making it a little more complex than it needed to be. By declaring subItems like below, they automatically become ListModels. And you can just refer to them in the delegate like you do labelText.

main.qml:

import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.15

ApplicationWindow {
    id: applicationWindow

    width: 300
    height: 200
    visible: true
    title: qsTr("01_Change_Model_Data")

    ListModel {
        id: listModel1
        ListElement {
            labelText: "ComboBox 1:"

            subItems: [
                ListElement {text: "First"},
                ListElement {text: "Second"},
                ListElement {text: "Third"}
            ]

        }
        ListElement {
            labelText: "ComboBox 2:"

            subItems: [
                ListElement {text: "First"},
                ListElement {text: "Second"},
                ListElement {text: "Third"}
            ]

        }
    }


    Button {
        id: loadUnloadBtn
        height: 24
        width: 50
        text: "Load"

        anchors {
            right: parent.right
            rightMargin: 20
            top: parent.top
            topMargin: 10
        }
        onClicked: {
            if(comboBoxAreaLoader.source == "") {
                comboBoxAreaLoader.source = "ComboBoxArea.qml"
            }else {
                comboBoxAreaLoader.source = ""
            }

        }
    }

    Loader {
        id: comboBoxAreaLoader
        anchors {
            top: parent.top
            topMargin: 10
            bottom: parent.bottom
            bottomMargin: 10
            left: parent.left
            leftMargin: 10
            right: parent.right
            rightMargin: 80
        }
    }
}

ComboBoxArea.qml:

import QtQuick 2.15
import QtQuick.Controls 2.15


Item {
    id: listViewDelegate
    ListView {
        id: listView1
        anchors.fill: parent

        model: listModel1
        delegate: listElementDelegate
        spacing: 6
    }

    Component {
        id: listElementDelegate
        Rectangle {
            id: delegateRectangleRoot

            height: 30
            width: 200
            Label {
                id: comboBoxNameLabel
                color: "red"
                width: 80
                height: 30
                anchors {
                    left: parent.left
                    leftMargin: 10
                }
                text: labelText
                verticalAlignment: Text.AlignVCenter
            }

            ComboBox {
                id: comboBox
                height: 30
                width: 100
                model: subItems

                anchors {
                    left: comboBoxNameLabel.right
                    leftMargin: 10
                    verticalCenter: comboBoxNameLabel.verticalCenter
                }
            }

        }

    }
}

Answered By – David K. Hess

Answer Checked By – Marilyn (BugsFixing Volunteer)

Leave a Reply

Your email address will not be published. Required fields are marked *