Dynamic delegate in Repeater



  • Hello,

    I want use Repeater with dynamic delegates.

    For example, I have this model :

     ListModel {
            id: listModelLabel
            ListElement {lib: "SITE"; type: "TEXT"}
            ListElement {lib: "REP"; type: "TEXT"}
            ListElement {lib: "FAB"; type: "AREA"}
    }
    

    and this components :

    Component {
        id: text
        Label { ... }
    }
    
    Component {
        id: area
        TextArea { ... }
    }
    

    In my Repeater, if the current item has the property type = TEXT, so the delegate will be text. But if type = AREA, the delegate will be area

    But, this doesn't work.

    Here, the code of my repeater :

    Repeater {
                id: repeater
                model: listModelLabel
                delegate: {
                    if (listModelLabel[index].type === "TEXT"){
                        text
                    }
                    if (listModelLabel[index].type === "AREA"){
                        area
                    }
                }
            }
    

    Do you know, if this is possible ?

    Thank you for your help.

    Bye.

    Charlie



  • You should use a Loader for that :

    Repeater {
        id: repeater
        model: listModelLabel
        Loader {
            sourceComponent: {
                if (listModelLabel[index].type === "TEXT") 
                    return text;
                if (listModelLabel[index].type === "AREA")
                    return area;
            }
        }
    }
    

    You could also use source instead of sourceComponent if you'd like to define your different delegates in their own file.



  • Completing the previous answer:

    • listModelLabel[index].type is not correct; use type instead, because it is automatically referring to the current element loaded from your List Model
    • I would suggest to use a Positioner (Row, Column, Grid, ...) for the repeater, otherwise everything will be overlapped. Add some spacing if needed.
    • Given the fact that both your components have a property called "text", you may change it according to the "lib" string in your model, for example. This is possible using "onLoaded" property of the Loader component.

    This is the code I used:

        ListModel {
           id: listModelLabel
           ListElement {lib: "SITE"; type: "TEXT"}
           ListElement {lib: "REP"; type: "TEXT"}
           ListElement {lib: "FAB"; type: "AREA"}
        }
    
        Component {
            id: text
            Label {
            }
        }
    
        Component {
            id: area
            TextArea {
            }
        }
    
        Column {
            Repeater {
                id: repeater
                model: listModelLabel
                delegate: Loader {
                    sourceComponent: {
                        if (type === "TEXT")
                            text;
                        if (type === "AREA")
                            area;
                    }
                    onLoaded: {
                        item.text = lib;
                    }
                }
            }
        }
    


  • Thank you. It works.


Log in to reply
 

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