This post gives an example how you can present the user some informative text or controls when a list view is empty.
Typical scenarios where this may be desirable are:
- When populating a list view with data from a network service.
- Show a Fetch data button if the list view is empty.
- Present any error that might occur while downloading/processing the data
- Showing search result in a list view.
- Present a No items found text to the user if the list view is empty.
In the example application I'm using an
ArrayDataModel, but it should work for
QListDataModel and
GroupDataModel too. Unfortunately, it will not work with
XmlDataModel because the class doesn't expose any function to query if the model is empty (at least not easily).
All of the data models mentioned above provides an
isEmpty() function which can be used to check if the data model contain any items or not.
The example should speaks for itself, so without any further ado, here's the code:
import bb.cascades 1.0
Page {
Container {
layout: DockLayout {}
ListView {
dataModel: ArrayDataModel {
id: model
// Bindable property which tells if the
// model is empty or not
property bool empty: true
// Populates model with dummy data
function populate() {
for (var i = 0; i < 10; i++) {
append({'title' : 'Item #' + i})
}
}
// The following signal handlers updates
// the empty property to correct state
onItemAdded: empty = isEmpty()
onItemRemoved: empty = isEmpty()
onItemUpdated: empty = isEmpty()
// You might see an 'unknown signal' error
// in the QML-editor, guess it's a SDK bug.
onItemsChanged: empty = isEmpty()
}
}
// Only visible when data model is empty.
// This should be declared after the ListView
// to prevent the ListView from consuming touch input etc
// Setting ListView's visible property to !model.empty will
// also work.
Label {
visible: model.empty //model.isEmpty() will not work
horizontalAlignment: HorizontalAlignment.Fill
verticalAlignment: VerticalAlignment.Center
text: qsTr("No entries yet\n\nPlease populate data model")
textStyle.base: SystemDefaults.TextStyles.BigText
textStyle.textAlign: TextAlign.Center
multiline: true
}
}
actions: [
// Action to populate/clear data model depending on state.
// Same here, model.isEmpty() will not behave as expected.
ActionItem {
title: model.empty ? qsTr("Populate") : qsTr("Clear")
onTriggered: model.empty ? model.populate() : model.clear()
ActionBar.placement: ActionBarPlacement.OnBar
}
]
}
Screenshots from the example application
A work-around is required because isEmpty() is only an invokable function in QML, and not a bindable property. The example will not behave as expected if model.isEmpty() is set as a value for the Label's visible property. The isEmpty() function is only called once when the Label is created and will never be re-evaluated again since it's not a bindable property (hint to Cascades API developers).
Please feel free to add other ways to accomplish this in the comments section.