1

I want to repeat from a string that I have in a variable.

From the documentation (and it works):

Column {
   Repeater {
       model: ["apples", "oranges", "pears"]
       Text { text: "Data: " + modelData }
   }
}

Now, I want to replace the model with a variable X, like this:

 Column {
    Repeater {
        model: X
        Text { text: "Data: " + modelData }
    }
 }

But it outputs nothing, no error. If I just show the content of X in a text label it shows this: ["apples", "oranges", "pears"], which is the exact content of my X variable.

So I'm not really sure how to approach it. I have to somehow make my string an object?

Using QT 5.12.6

2 Answers 2

2

Firstly, contrary to your title, you can make a QML Repeater work with a variable. The question wasn't clear on exactly what you did try, but, your use case indicates an array.

I present 3 ways of declaring a property that you can use in a Repeater:

    property var fruitArrayQt5: ["apples", "oranges", "pears"]
    property list<string> fruitArrayQt6: ["apples", "oranges", "pears"]
    ListModel {
        id: fruitModel
        ListElement { name: "apples" }
        ListElement { name: "oranges" }
        ListElement { name: "pears" }
    }

In the case of fruitArrayQt5 the property is declared as a var. Which, unfortunately, means subsequent changes to the array (e.g. via push/remove/etc) will not be signaled and the Repeater will not react to changes. The workaround is you have to keep reassigning the Repeater's model.

In the case of fruitArrayQt6 the property is declared as a list<string>. Because it is using the new Qt6 list primitive, it means subsequent changes to the array (e.g. via push/remove) WILL be signaled to the Repeater. It requires Qt6, possibly Qt6.4 to use this.

In the case of fruitModel changes done to the ListModel (e.g. via append/remove) WILL also be signal to the Repeater.

In the following example, we populate three Repeaters demonstrating the 3 types above. When you click on the Add button you see that the Repeaters only reacts to changes done to fruitArrayQt6 and fruitModel. The Repeater attached to fruitArrayQt5 doesn't react to changes. You have to enable the Workaround check box to force an update to Repeater's model property:

import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
Page {
    property var fruitArrayQt5: ["apples", "oranges", "pears"]
    property list<string> fruitArrayQt6: ["apples", "oranges", "pears"]
    ListModel {
        id: fruitModel
        ListElement { name: "apples" }
        ListElement { name: "oranges" }
        ListElement { name: "pears" }
    }
    RowLayout {
        width: parent.width
        ColumnLayout {
            Layout.alignment: Qt.AlignTop
            Repeater {
                model: fruitModel
                Text { text: "fruitModel: " + name }
            }
        }
        ColumnLayout {
            Layout.alignment: Qt.AlignTop
            Repeater {
                id: arrayRepeater
                model: fruitArrayQt5
                Text { text: "fruitArrayQt5: " + modelData }
            }
        }
        ColumnLayout {
            Layout.alignment: Qt.AlignTop
            Repeater {
                model: fruitArrayQt6
                Text { text: "fruitArrayQt6: " + modelData }
            }
        }
    }
    footer: Frame {
        RowLayout {
            CheckBox {
                id: workaround
                text: qsTr("Workaround")
            }
            Button {
                text: qsTr("Add")
                onClicked: {
                    fruitModel.append({name:"bananas"});
                    fruitArrayQt5.push("bananas");
                    fruitArrayQt6.push("bananas");
                    if (workaround.checked)
                        arrayRepeater.model = fruitArrayQt5;
                }
            }
            Button {
                text: qsTr("Reset")
                onClicked: {
                    while (fruitModel.count > 3)
                        fruitModel.remove(fruitModel.count - 1);
                    while (fruitArrayQt5.length > 3)
                        fruitArrayQt5.pop();
                    while (fruitArrayQt6.length > 3)
                        fruitArrayQt6.pop();
                    if (workaround.checked)
                        arrayRepeater.model = fruitArrayQt5;
                }
            }
        }
    } 
}

You can Try it Online!

Sign up to request clarification or add additional context in comments.

Comments

2

From the documentation:

Property names must begin with a lower case letter and can only contain letters, numbers and underscores.

When I'm using a upper case letter like X as the property name I get the following compile error:

error: Property names cannot begin with an upper case letter

If you use a lowercase x it will instead use the predefined x property of Repeater as it inherits Item.

If you want to make sure you get the correct x you should use ids like so:

import QtQuick
import QtQuick.Controls
import QtQuick.Layouts

Window {
    id: root
    width: 400
    height: 300
    visible: true

    property var x: ["apples", "oranges", "pears"]

    Column {
       Repeater {
           model: root.x
           Text { text: "Data: " + modelData }
       }
    }
}

As Jürgen Lutz said the type of your property is also important to know. It has to be of var type. If you are using Qt 6.4 and above you can also use the list type like so:

property list<string> test: ["apples", "oranges", "pears"]

4 Comments

Thank you! But I wasn't clear enough, sorry about that. X is just a way of saying the name of the variable. My variable is longer and all lower case. Also, I'm trying to do this in a listView, so for each new row the repetear should start again with fresh content from the variable (comes from a DB field), so declaring it at the top as you did does not fit my needs. Sorry again for not being clearer, again. I'm still not sure how to approach this. Also, I'm using QT 5.12.6
So can you share the property definition? Without that definition I can't tell you what the reason could be. Also are you using QQmlListProperty on the C++ side?
You are using a ListView which means you are using the inbuilt repeater? It gets more and more confusing :)
I had no idea that you can use list<string> in Qt6.4.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.