uniquenamehere
uniquenamehere

Reputation: 1949

Access ListView model within the Repeater component in the delegate

I am using a ListView with a model and a delegate.

The model is a simple ListModel with three items. Each item has a value with the key myFirstRole.

The delegate contains a Repeater component to create an arbitrary number of Labels. The Labels have to use data from the model.

The model of the repeater can not be set to the Listview's model as I have the Repeater using other data.

Here is a minimal example of what I am trying to achieve:

//MyDelegate.qml
Component {

    Item {
        id: root

        width: childrenRect.width
        height childrenRect.height

        Repeater {
            model: 5 //It's not an option to set the repeaters model to the ListViews model. This example just illustrates my problem.

            Label {
                text: root.ListView.view.model.myFirstRole //This is the line where I want to be able to access the ListView's model, but I can't figure out how to properly reefer to it.
            }
        }
    }
}

//MyListView.qml
ListView {
    id: root

    delegate: MyDelegate {}
    model: ListModel {
        ListElement {
            myFirstRole: "one"
        }
        ListElement {
            myFirstRole: "two"
        }
        ListElement {
            myFirstRole: "three"
        }
    }
}

Using Qt 5.7.0 with MSVC2015 32bit

Upvotes: 2

Views: 4314

Answers (2)

Mitch
Mitch

Reputation: 24416

I think that you can't access the roles via the special model property mentioned here (which is what I'm assuming you were trying to do) from the scope of the Repeater. Instead, you can declare a property at the root level of the component that can then be used in nested scopes:

import QtQuick 2.6
import QtQuick.Window 2.2

Window {
    visible: true
    width: 640
    height: 480

    ListView {
        anchors.fill: parent
        model: ListModel {
            ListElement { myFirstRole: "Dog" }
            ListElement { myFirstRole: "Cat" }
        }

        delegate: Item {
            id: root

            width: childrenRect.width
            height: childrenRect.height

            property string myFirstRoleData: myFirstRole

            Repeater {
                model: 5

                Text {
                    text: myFirstRoleData
                }
            }
        }
    }
}

This might get a bit tedious if you have a lot of properties though. From some quick playing around, it looks like it's also possible to store the entire model object in a property:

import QtQuick 2.6
import QtQuick.Window 2.2

Window {
    visible: true
    width: 640
    height: 480

    ListView {
        anchors.fill: parent
        model: ListModel {
            ListElement { myFirstRole: "Dog" }
            ListElement { myFirstRole: "Cat" }
        }

        delegate: Item {
            id: root

            width: childrenRect.width
            height: childrenRect.height

            property var modelData: model

            Repeater {
                model: 5

                Text {
                    text: root.modelData.myFirstRole
                }
            }
        }
    }
}

modelData is probably not the best name to use though, seeing as Qt uses that name for models with only one role, but... if you're going with this approach, you're gonna have more than one role anyway. :)

It looks like Qt Quick Controls' (1) Tumbler does this too.

Upvotes: 4

derM
derM

Reputation: 13711

//MyDelegate.qml
Item {
    id: root
    property var listViewModel // pass the model data to here
    width: 100
    height: 50

    Column {
        Repeater {
            model: 5 // Use a different model here
            Text {
                width: 50
                height: 10
                text: listViewModel.myFirstRole //This is the line where I want to be able to access the ListView's model, but I can't figure out how to properly reefer to it.
            }
        }
    }
}

//MyListView.qml
ListView {
    id: root
    width: 100
    height: 500

    delegate: MyDelegate {
        listViewModel: model // set the model data here
    }
    model: ListModel {
        ListElement {
            myFirstRole: "one"
        }
        ListElement {
            myFirstRole: "two"
        }
        ListElement {
            myFirstRole: "three"
        }
    }
}

See the comments in the code. It is not trivial to guess what you want to achive, but I hope I guessed right.

Upvotes: 1

Related Questions