Access model in another qml component



  • Hi,

    I need to access a model from another qml component. My model holds four strings:

    • deviceImage
    • euro
    • kwh
    • time

    @
    //...

    Row {
    id: deviceRow
    spacing: 20

         Repeater {
                          id: deviceRepeater
                          model: *timeslotmodel*
    
                          Button {id: deviceImageButton; anchors.verticalCenter: parent.verticalCenter; iconSource: *deviceImage*; width: 100; height: 100; }
    
                            }
                        }
                    }
                }
            }
    
    
            TimelineDeviceDetail {}
    

    //...
    @

    And I need to access "euro, kwh, time" in TimelineDeviceDetail:

    @
    //...
    Text {
    id: euroText
    text: euro
    anchors.top: parent.top
    anchors.topMargin: 20
    anchors.left: parent.left
    anchors.leftMargin: 20
    font.pixelSize: 12
    }

        Text {
            id: kwhText
            *text: kwh*
            anchors.top: parent.top
            anchors.topMargin: 20
            anchors.horizontalCenter: parent.horizontalCenter
            font.pixelSize: 12
        }
    
        Text {
            id: timeText
            *text: time*
            anchors.top: parent.top
            anchors.topMargin: 20
            anchors.right: parent.right
            anchors.rightMargin: 20
            font.pixelSize: 12
        }
    

    //...
    @

    How can I do this? How can I delegate them to TimelineDeviceDetail?

    Thanks


  • Moderators

    Hi,

    Since you are using a Repeater and Repeater can have delegate, you can assign TimelineDeviceDetail as a delegate to Repeater and thus
    TimelineDeviceDetail will have access to all the model roles.
    Is this what you are looking for ?



  • Thanks for your replay.

    I add a delegate to my repeater:

    @
    Repeater {
    id: deviceRepeater
    model: timeslotmodel
    delegate: TimelineDeviceDetail {}

                                Button {id: deviceImageButton; anchors.verticalCenter: parent.verticalCenter; iconSource: deviceImage; width: 100; height: 100; onClicked: setVisibleEffect(detailRectangle, deviceItem); style: TimelineDeviceButtonStyle{} }
    
                            }
                        }
                    }
                }
            }
    
    
            TimelineDeviceDetail {
                id: detailRectangle }
    

    @

    But I still get a ReferenceError:

    @
    qrc:///TimelineDeviceDetail.qml:21: ReferenceError: euro is not defined
    qrc:///TimelineDeviceDetail.qml:31: ReferenceError: kwh is not defined
    qrc:///TimelineDeviceDetail.qml:40: ReferenceError: time is not defined
    @

    Any suggestions?


  • Moderators

    It should be accessible through model property. i.e for eg. model.euro



  • I removed the delegate:

    @
    //...
    Repeater {
    id: deviceRepeater
    model: timeslotmodel

                                Button {id: deviceImageButton; anchors.verticalCenter: parent.verticalCenter; iconSource: deviceImage; width: 100; height: 100; onClicked: setVisibleEffect(detailRectangle, deviceItem); style: TimelineDeviceButtonStyle{} }
    
                            }
                        }
                    }
                }
            }
    
            TimelineDeviceDetail {
                id: detailRectangle }
    

    //...
    @

    ... and add the model to my TimelineDeviceDetail view:

    @
    /...
    Text {
    id: euroText
    Component.onCompleted: console.log("euro: " + timeslotmodel.euro)
    text: timeslotmodel.euro
    anchors.top: parent.top
    anchors.topMargin: 20
    anchors.left: parent.left
    anchors.leftMargin: 20
    font.pixelSize: 12
    }

        Text {
            id: kwhText
             Component.onCompleted: console.log("kwh: " + kwh)
            text: timeslotmodel.kwh
            anchors.top: parent.top
            anchors.topMargin: 20
            anchors.horizontalCenter: parent.horizontalCenter
            font.pixelSize: 12
        }
    
        Text {
            id: timeText
            text: timeslotmodel.time
            anchors.top: parent.top
            anchors.topMargin: 20
            anchors.right: parent.right
            anchors.rightMargin: 20
            font.pixelSize: 12
        }
    

    /...
    @

    Error:

    @
    qrc:///TimelineDeviceDetail.qml:22:19: Unable to assign [undefined] to QString
    @


  • Moderators

    That was expected as TimelineDeviceDetail wouldn't know which model item to fetch.
    Why not assign TimelineDeviceDetail as a delegate to Repeater ?
    Did you try
    @
    text: model.euro
    @

    as suggested earlier ?



  • Same code as in my last post and I add

    @
    delegate: TimelineDeviceDetail {}
    @

    to my repeater.

    I still get the same error


  • Moderators

    and how TimelineDeviceDetail body looks like now ?



  • This is my complete code:

    TimelineVertical:

    @
    import QtQuick 2.0
    import QtQuick.Controls 1.2

    Rectangle {
    id: timelineRectangle
    anchors.fill: parent

    //background
    Image {
        id: timelineImage
        anchors.rightMargin: 0
        anchors.bottomMargin: 0
        anchors.leftMargin: 0
        anchors.topMargin: 0
        anchors.fill: parent
        z: 0
        source: "content/image/background/background.png"
    }
    
    ListView {
        id: timelineListView
        clip: false
        spacing: 70
        anchors.fill: parent
        anchors.margins: 50
        model: timelineModel
        delegate: Item {
            id: deviceItem
            anchors.right: parent.right
            anchors.rightMargin: 0
            anchors.left: parent.left
            anchors.leftMargin: 0
            height: 220
    
            Row {
                id: timeslotRow
                width: 0
                spacing: 0
    
                //date
                Rectangle {
                    id: dateRectangle
                    width: 220
                    height: 220
                    color: "#16A085"
                    radius: 100
                    border.width: 8
                    border.color: "#2ABF3C"
    
                    TimelineTextStyle {
                        id: dateText
                        text: date
                        width: 130
                        height: 150
                        wrapMode: Text.WordWrap
                        verticalAlignment: Text.AlignVCenter
                        horizontalAlignment: Text.AlignHCenter
                        anchors.horizontalCenter: parent.horizontalCenter
                        anchors.centerIn: parent
                    }
                }
    
                //vertical line
                Rectangle {
                    id: verticalLineRectangle
                    height: 10
                    width: 60
                    radius: 0
                    anchors.verticalCenterOffset: 0
                    color: "#16A085"
                    anchors.verticalCenter: dateRectangle.verticalCenter
                }
    
                //devices
                Rectangle {
                    id: timeslotRectangle
                    width: 780
                    anchors.verticalCenter: timeslotRow.verticalCenter;
                    height: 150
                    color: "#FFFFFF"
                    radius: 4
                    opacity: 0.70
    
                    ScrollView {
                        id: timeslotScrollview
                        anchors.fill: parent
                        clip: true
                        flickableItem.flickableDirection: Flickable.HorizontalFlick
    
                        Row {
                            id: deviceRow
                            spacing: 20
    
                            Repeater {
                                id: deviceRepeater
                                model: timeslotmodel
                                delegate: TimelineDeviceDetail {}
    
                                Button {id: deviceImageButton; anchors.verticalCenter: parent.verticalCenter; iconSource: deviceImage; width: 100; height: 100; onClicked: setVisibleEffect(detailRectangle, deviceItem); style: TimelineDeviceButtonStyle{} }
    
                            }
                        }
                    }
                }
            }
    
            TimelineDeviceDetail {
                id: detailRectangle }
    

    // // property alias euroValue: euro
    // // property alias kwhValue: kwh
    // // property alias timeValue: time

    // // property string euroValue: euro
    //// property string kwhValue: "0,20 kwh"
    // // property string timeValue: deviceImageButton.iconSource
    // }

            //horizontal line
            Rectangle {
                id: timelineLineRectangle
                width: 10
                height: 400
                color: "#16a085"
                radius: 1
                z: -1
                anchors.left: parent.left
                anchors.leftMargin: 105
                anchors.top: parent.top
                anchors.topMargin: 215
            }
        }
    }
    
    TimelineFilter {}
    
    function setVisibleEffect(detailRectangle, deviceItem) {
        console.log("detailRectangle.visible:" + detailRectangle.visible)
    
        if(detailRectangle.visible === false) {
            detailRectangle.visible = true
            deviceItem.height = 400;
        } else {
            detailRectangle.visible = false
            deviceItem.height = 220;
        }
    }
    

    }
    @



  • and my TimelineDeviceDetail:

    @
    import QtQuick 2.0

    //detail
    Rectangle {
    id: rectangle2
    width: 0
    height: 200
    color: "#FFFFFF"
    radius: 4
    anchors.right: parent.right
    anchors.rightMargin: 100
    opacity: 0.70
    anchors.left: timelineLineRectangle.right
    anchors.leftMargin: 165
    anchors.top: timeslotRow.bottom
    anchors.topMargin: 0
    visible: true //debugging: make it false

        Text {
            id: euroText
    

    // Component.onCompleted: console.log("euro: " + timeslotmodel.euro)
    text: timeslotmodel.euro
    anchors.top: parent.top
    anchors.topMargin: 20
    anchors.left: parent.left
    anchors.leftMargin: 20
    font.pixelSize: 12
    }

        Text {
            id: kwhText
    

    // Component.onCompleted: console.log("kwh: " + timeslotmodel.kwh)
    text: timeslotmodel.kwh
    anchors.top: parent.top
    anchors.topMargin: 20
    anchors.horizontalCenter: parent.horizontalCenter
    font.pixelSize: 12
    }

        Text {
            id: timeText
            text: timeslotmodel.time
            anchors.top: parent.top
            anchors.topMargin: 20
            anchors.right: parent.right
            anchors.rightMargin: 20
            font.pixelSize: 12
        }
    
    
    Rectangle {
        id: rectangle1
        height: 2
        color: "#34495e"
        anchors.top: parent.top
        anchors.topMargin: 60
        anchors.right: parent.right
        anchors.rightMargin: 0
        anchors.left: parent.left
        anchors.leftMargin: 0
    
    }
    

    }
    @


  • Moderators

    So here, instead of
    @
    text: timeslotmodel.euro
    @

    try
    @
    text: model.euro
    @



  • I changed it but still same error:

    @
    qrc:///TimelineDeviceDetail.qml:42:19: Unable to assign [undefined] to QString
    @


  • Moderators

    That's strange. Is it for all 3 or just time ?


  • Moderators

    Also I see
    @
    TimelineDeviceDetail {
    id: detailRectangle }
    @

    after the Repeater. Remove it. The error could be because of that too. Since it is not is scope of Repeater, it will also attract those errors.



  • Yes, for all three. I removed the TimelineDeviceDetail.

    I get no errors but how can I include the TimelineDeviceDetail back to my TimelineVertical after I deleted:

    @
    TimelineDeviceDetail {
    id: detailRectangle }
    @



  • I want the TimelineDeviceDetail exactly at the position where I deleted it.


  • Moderators

    So you have TimelineDeviceDetail.qml file. You can assign an id there.



  • ... I don't get it, can you make a quick example? In my opinion the "delegate" just delegate the model to TimelineDeviceDetail and to make TimelineDeviceDetail visible I have to declare it somewhere in TimelineVertical...


  • Moderators

    From your earlier posts i assume that you have a separate TimelineDeviceDetail.qml file. So define an id here.
    @
    import QtQuick 2.0

    Rectangle {
    // id: rectangle2
    id: detailRectangle
    width: 0
    height: 200
    color: "#FFFFFF"
    radius: 4
    anchors.right: parent.right
    ...
    @

    and it will be accessible as before.

    Edited



  • Yes thats correct I have a separate file: TimelineDeviceDetail.qml


  • Moderators

    So just define an id (detailRectangle) there and it will be accessible. See my earlier edited post.



  • So you mean:

    in TimelineDeviceDetail.qml

    @
    //detail
    Rectangle {
    id: detailRectangle
    width: 0
    height: 200
    color: "#FFFFFF"
    radius: 4
    anchors.right: parent.right
    anchors.rightMargin: 100
    opacity: 0.70
    anchors.left: timelineLineRectangle.right
    anchors.leftMargin: 165
    anchors.top: timeslotRow.bottom
    anchors.topMargin: 0
    visible: true //debugging: make it false

        Text {
            id: euroText
    

    // Component.onCompleted: console.log("euro: " + timeslotmodel.euro)
    text: model.euro
    anchors.top: parent.top
    anchors.topMargin: 20
    anchors.left: parent.left
    anchors.leftMargin: 20
    font.pixelSize: 12
    }

        Text {
            id: kwhText
    

    // Component.onCompleted: console.log("kwh: " + timeslotmodel.kwh)
    text: model.kwh
    anchors.top: parent.top
    anchors.topMargin: 20
    anchors.horizontalCenter: parent.horizontalCenter
    font.pixelSize: 12
    }

        Text {
            id: timeText
            text: model.time
            anchors.top: parent.top
            anchors.topMargin: 20
            anchors.right: parent.right
            anchors.rightMargin: 20
            font.pixelSize: 12
        }
    

    //...
    @

    and int TimelineVertical.qml:

    @
    Repeater {
    id: deviceRepeater
    model: timeslotmodel
    delegate: TimelineDeviceDetail {}
    // Component.onCompleted: console.log("euroValueTest: " + timeslotmodel.euro)
    Button {id: deviceImageButton; anchors.verticalCenter: parent.verticalCenter; iconSource: deviceImage; width: 100; height: 100; /onClicked: setVisibleEffect(detailRectangle, deviceItem);/ style: TimelineDeviceButtonStyle{} }

                            }
                        }
                    }
                }
            }
    
             TimelineDeviceDetail {} //set the view where I need it
    

    @

    But than I get the same error as before:

    qrc:///TimelineDeviceDetail.qml:22:19: Unable to assign [undefined] to QString
    qrc:///TimelineDeviceDetail.qml:33:19: Unable to assign [undefined] to QString
    qrc:///TimelineDeviceDetail.qml:42:19: Unable to assign [undefined] to QString



  • I put the code from TimelineDeviceDetail.qml back to TimelineVertical.qml to make it simple. It turned out that it's even there not accessible...

    @
    Row {
    id: deviceRow
    spacing: 20

                            Repeater {
                                id: deviceRepeater
                                model: timeslotmodel
                                delegate: detailRectangle
    
                                Button {id: deviceImageButton; anchors.verticalCenter: parent.verticalCenter; iconSource: deviceImage; width: 100; height: 100; onClicked: setVisibleEffect(detailRectangle, deviceItem); style: TimelineDeviceButtonStyle{} }
                            }
                        }
                    }
                }
            }
    
            Rectangle {
                id: detailRectangle
                width: 0
                height: 200
                color: "#FFFFFF"
                radius: 4
                anchors.right: parent.right
                anchors.rightMargin: 100
                opacity: 0.70
                anchors.left: timelineLineRectangle.right
                anchors.leftMargin: 165
                anchors.top: timeslotRow.bottom
                anchors.topMargin: 0
                visible: false //debugging: make it false
    
                Text {
                    id: euroText
                    text: model.euro
                    anchors.top: parent.top
                    anchors.topMargin: 20
                    anchors.left: parent.left
                    anchors.leftMargin: 20
                    font.pixelSize: 12
                }
    
                Text {
                    id: kwhText
                    text: model.kwh
                    anchors.top: parent.top
                    anchors.topMargin: 20
                    anchors.horizontalCenter: parent.horizontalCenter
                    font.pixelSize: 12
                }
    
                Text {
                    id: timeText
                    text: model.time
                    anchors.top: parent.top
                    anchors.topMargin: 20
                    anchors.right: parent.right
                    anchors.rightMargin: 20
                    font.pixelSize: 12
                }
    
    
                Rectangle {
                    id: rectangle1
                    height: 2
                    color: "#34495e"
                    anchors.top: parent.top
                    anchors.topMargin: 60
                    anchors.right: parent.right
                    anchors.rightMargin: 0
                    anchors.left: parent.left
                    anchors.leftMargin: 0
    
                }
            }
    

    @

    @
    Unable to assign [undefined] to QString
    @


  • Moderators

    If you define delegate in same file then you will need to encapsulate it in Component.

    Going to the previous, you have again added TimelineDeviceDetail there. Please remove it or you will get the same errors. Please refer my earlier posts.
    TimelineDeviceDetail will be accessible using its id even if it is specified in separate file.



  • Ok thanks for that advise. Can you please tell my if I remove "TimelineDeviceDetail" from "TimelineVertical" how to include the TimelineDeviceDetail in TimelineVertical? Or can you make "will be accessible using its id..." a little bit more clear?

    Thanks


  • Moderators

    Ok. Just revisited the posts. I too got confused. Lots of code here :)
    First Why would you want TimelineDeviceDetail outside the delegate as it has already been assigned as delegate to repeater ?

    Just created a small example related to above:
    @
    //TimelineDeviceDetail.qml
    import QtQuick 2.3
    Rectangle {
    id: detailRectangle
    y: index*40
    width: 300
    height: 40
    color: "lightgray"
    Text {
    anchors.centerIn: parent
    text: model.euro
    }
    }

    //main.qml
    import QtQuick 2.3
    Rectangle {
    width: 300
    height: 180

    ListModel {
        id: mymodel
        ListElement {
            euro: "3"
        }
        ListElement {
            euro: "6"
        }
    }
    
    Repeater {
        model: mymodel
        delegate: TimelineDeviceDetail {}
    }
    

    }
    @

    Here TimelineDeviceDetail is able to access the model role(euro).
    Now can you format your question and requirements according to above example so it will be easier for me to understand?



  • That's a good idea to simplify that. Did you compile the example?

    I get the following error:

    @
    qrc:///TestTimeline.qml:12: ReferenceError: model is not defined
    @

    Test.qml:

    @
    import QtQuick 2.3
    import QtQuick.Controls 1.2
    import QtQuick.Layouts 1.1

    Rectangle {
    id: rectangle1
    anchors.fill: parent

    Rectangle {
        width: 300
        height: 180
    
        ListModel {
            id: mymodel
            ListElement {
                euro: "3"
            }
            ListElement {
                euro: "6"
            }
        }
    
        Repeater {
            model: mymodel
            delegate: TestTimeline {}
    
            Text {
                text: euro
            }
        }
    }
    

    }
    @

    TestTimeline.qml:

    @
    import QtQuick 2.3
    import QtQuick.Controls 1.2
    import QtQuick.Layouts 1.1

    Rectangle {
    id: detailRectangle
    width: 300
    height: 40
    color: "blue"
    Text {
    anchors.centerIn: parent
    text: model.euro
    }
    }
    @

    I made some little changes on your code.



  • I set up a new project just to test this little example and the same here. Any suggestions?



  • I fixed this with JavaScript, probably not this best way but it works for me...

    TimleineVertical.qml:

    @
    Row {
    id: deviceRow
    spacing: 20

                            Repeater {
                                id: deviceRepeater
                                model: attributes
    
                                Button {id: deviceImageButton;
                                    anchors.verticalCenter: parent.verticalCenter;
                                    iconSource: deviceImage;
                                    width: 100;
                                    height: 100;
                                    onClicked: setVisibleDetail(detailRectangle, deviceItem), setTest(euro, kwh, time, euroText, kwhText, timeText)
    
                                    style: TimelineDeviceButtonStyle{} }
    
                            }
    

    @

    JavaScript to set the values from the model for the text element:

    @
    function setTest(euro, kwh, time, euroText, kwhText, timeText) {
    euroText.text = euro;
    kwhText.text = kwh;
    timeText.text = time;
    }
    @

    Text element:

    @
    Text {
    id: euroText
    anchors.top: parent.top
    anchors.topMargin: 30
    anchors.left: parent.left
    anchors.leftMargin: 20
    font.pixelSize: 12
    }
    @


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.