passing lists of data to a Component
-
@mzimmers I think you are on the right track, but you seem to be stuck on some minor issues.
First, remember the strong seperation of model/view. In this specific case you can easily have one model that feeds all 3 types of views. You KNOW that a view will only ask for certain properties if the data is a certain type, as such you can optimize your model code to match (add asserts, even).
So, in short, to feed your 3 types of views you should only have one backing model. It simply has different properties you query for a specific view.
Second,
you can use a Loader with a construction like:ListView { model: someModel Loader { source: { if (model.someProperty) return "./Page1.qml"; if (model.foo) return "./Page2.qml"; return "./Page3.qml"; } }
Then your pages simply need to use the model property to fetch the data they want to use.
Page1.qml Label { text: model.something }
-
@TomZ I think this is moving in the right direction. A couple points:
I am indeed maintaining a single model. It contains a list of all the equipment items in the system.
There will be multiple equipment items of the same category in a system. For this reason, I need to somehow inform my Page1/2/3.qml files of the equipment object I'm using. By the time I'm in this QML area, I've already accessed the model and have a single instance of Equipment in my QML.
Also (minor) when I changed my Flickable to a ListView, it no longer flicks. Here's the complete code for the section:
// Flickable { ListView { boundsBehavior: Flickable.StopAtBounds clip: true contentHeight: contentItem.childrenRect.height implicitWidth: parent.width implicitHeight: innerPane.availableHeight EquipmentConfigList { // this would become Page1/2/3.qml id: equipmentConfigList Layout.fillHeight: true Layout.preferredWidth: rightColumn.availableWidth equipment: equipmentCopy } }
Any idea why it doesn't flick for me anymore?
Thanks for the help...
-
If you want to have different delegate components based on a type role, use DelegateChooser instead of Loader for delegates.
If you want to have a single generic delegate, you could define all the possible fields and conditionally show them if there is a corresponding property. Or fetch the properties from the meta-object. Do you want to do that though? What if you want to display a gauge/slider? How would you define the min/max value?
-
@GrecKo said in passing lists of data to a Component:
What if you want to display a gauge/slider? How would you define the min/max value?
You're a mind reader - I will indeed need to do that elsewhere (the customer wants separate pages for viewing and editing the Equipment fields). I was starting with the easy (readonly) stuff.
I'm still having trouble putting this all together, though. I need a Flickable (or ListView) that will conditionally display properties of the Equipment object based on the category of the equipment.
Here's the basis of the Equipment class:
enum EquipmentCategory { CATEGORY_UNKNOWN, CATEGORY_VSP, CATEGORY_HEATER, CATEGORY_HEATPUMP, // ... } class Equipment : public QObject { Q_OBJECT QML_ELEMENT EquipmentCategory m_category = CATEGORY_UNKNOWN; // exposed to QML // ... }
So, how do I use a DelegateChooser here:
Flickable { // what is my model? DelagateChooser { role: category DelegateChoice { role: CATEGORY_VSP // this doesn't seem right VspDelegate {} // contained an another file } DelegateChoice { role: CATEGORY_HEATER HeaterDelegate {} // contained an another file } } }
Is this on the right track?
Thanks...
-
@mzimmers said in passing lists of data to a Component:
role: CATEGORY_VSP // this doesn't seem right
use
roleValue
here. And properly expose your enum type to QML.The
role
property ofDelegateChooser
is a string, so specify the role name as a string here. -
@GrecKo so, this is what I have now (and it seems to work):
ListView { anchors.fill: parent model: equipmentCopy clip: true boundsBehavior: Flickable.StopAtBounds delegate: DelegateChooser { role: "category" DelegateChoice { roleValue: NgaUI.CATEGORY_VSP delegate: EquipmentConfigList { equipment: equipmentCopy } } } }
It's a little foreign to me, as I've never used an object as a model, but everything seems to work. Thanks for all the help on this.
-
@GrecKo Before I close this topic, I do have a couple of follow-up questions:
-
I don't seem to be using a list in the "classical" sense, in that I'm only displaying one item. I realize that a delegate (and therefore, a DelegateChooser) needs a list, but...is there a preferred way to implement what I'm doing? Without a list?
-
(sort of related) is it OK to use an object as the model for a ListView? It seems to work OK, but there's nothing in the docs that explicitly says I can do this, so I want to make sure this is licit.
Thanks...
-
-
@mzimmers I didn't realize you didn't want to use this is a model/view but yes it is indeed supported to have a single object as a model. You were 1 link away ;) https://doc.qt.io/qt-6/qtquick-modelviewsdata-modelview.html#object-instances-as-models
using Loader like mentioned by TomZ is an alternative.
-
@GrecKo yeah, this is a weird use case. I actually do want a list, just not a list in the Qt model/view/delegate sense. Ideally, I'd like to create a list (array/vector/whatever) of the properties I want to display, and pass it into a universal component for display, but creating and using that structure seems to be a bit out of reach for JS/QML/me. It's OK; this approach is working, if a bit inelegant.
-