eri
eri

Reputation: 3504

QML render list in list

My simplified code is

import QtQuick 2.0

Item {

    ListModel {
        id: items_model
        dynamicRoles: true
    }

    Component.onCompleted: {
        var data = {
            "items": [{
                    "name": "test1",
                    "rows": ["1", "2", "3"]
                }, {
                    "name": "test2",
                    "rows": ["1", "2", "3"]
                }, {
                    "name": "test3",
                    "rows": ["1", "2", "3"]
                }]
        }

        data.items.forEach(function (element) {
            items_model.append(element)
            console.log(element.rows)
        })

        console.log(items_model.count)
    }

    ListView {
        orientation: ListView.Horizontal

        model: items_model
        delegate: Item {

            height: parent.height
            width: 50

            Column {
                anchors.fill: parent
                Text {
                    text: name
                }

                Repeater {
                    model: rows
                    delegate: Text {
                        text: rows.get(index) + " " + index
                        Component.onCompleted: {
                            console.log(rows.get(index))
                        }
                    }
                }
            }
        }
    }
}

But I have DynamicRoleModelNode, not text

qml: DynamicRoleModelNode(0x563014585300)
qml: DynamicRoleModelNode(0x563014585330)
qml: DynamicRoleModelNode(0x563014585360)
qml: DynamicRoleModelNode(0x563014570350)
qml: DynamicRoleModelNode(0x563014570380)
qml: DynamicRoleModelNode(0x5630145703b0)
qml: DynamicRoleModelNode(0x563014558e00)
qml: DynamicRoleModelNode(0x563014558e30)
qml: DynamicRoleModelNode(0x563014558e60)

modelData not provided here besause of rows converted to QQmlListModel

How can i extract text from it?

Upvotes: 0

Views: 398

Answers (2)

eri
eri

Reputation: 3504

As workaround wrap text to object

    data.items.forEach(function (element) {
        element.rows.forEach(function (item, index) {
              element.rows[index] = {text: item}
        })

        items_model.append(element)
    })

and

Repeater {

                model: rows
                delegate: Text {
                    text: text
                }
          }

Upvotes: 1

David K. Hess
David K. Hess

Reputation: 17246

Take a look at the documentation about models here:

https://doc.qt.io/qt-5/qtquick-modelviewsdata-modelview.html#models

In particular:

Models that do not have named roles (such as the ListModel shown below) will have the data provided via the modelData role. The modelData role is also provided for models that have only one role. In this case the modelData role contains the same data as the named role.

So in your case, the string data you are looking for will be provided in a variable called modelData in the context of the Text component.

Note that in your specific case, this cannot be done directly because the ListModel is converting the child role items into a ListModel itself instead of a StringList model. This may be a bug in Qt as you would think you should normally get a StringList there.

To work around it, you can store your child items in a separate map and apply them directly to the Repeater so that you correctly get a StringList model and then modelData will indeed work.

Something like this:

    property var itemsMap: ({
                                "test1": ["1", "2", "3"],
                                "test2": ["1", "2", "3"],
                                "test3": ["1", "2", "3"]
                            })

    Item {

        ListModel {
            id: items_model
            dynamicRoles: true
        }

        Component.onCompleted: {

            var data = {
                "items": [{
                        "name": "test1"
                    }, {
                        "name": "test2"
                    }, {
                        "name": "test3"
                    }]
            }

            data.items.forEach(function (element) {
                items_model.append(element)
            })

            console.log(items_model.count)
        }

        ListView {
            orientation: ListView.Horizontal

            model: items_model
            delegate: Item {

                height: parent.height
                width: 50

                Column {
                    anchors.fill: parent
                    Text {
                        text: name
                    }

                    Repeater {
                        model: itemsMap[name]
                        delegate: Text {
                            text: modelData
                        }
                    }
                }
            }
        }
    }

Upvotes: 1

Related Questions