Learn what Felgo offers to help your business succeed. Start your free evaluation today! Felgo for Your Business

JsonListModel

A proxy view model for JSON data sources. More...

Import Statement: import Felgo 4.0
Since: Felgo 2.18.3

Properties

Methods

Detailed Description

JsonListModel allows to transform your JSON data into a QML ListModel for usage with e.g. an AppListView.

With Felgo, you develop apps using QML and JavaScript. This makes it easy to work with JSON data and REST APIs, as you can see with the examples of the Access a REST Service topic. But JSON objects are a variant data type. This means that there's no defined data structure that default UI components can expect. When you use this variant type as your data source for e.g. an AppListView, the list view is not able to fully utilize all its features.

For example, if individual data properties or list entries in your JSON data are modified, the list view can not track these changes. Thus, each modification of the data requires to recreate and redraw the list from scratch. Of course this is not ideal in terms of performance and user experience.

In addition, advanced features like list sections or transition animations are not available. The JsonListModel solves all these issues. It integrates QSyncable, a ListModel implementation by Ben Lau. You can also find the full project on GitHub.

The JsonListModel holds a local copy of the specified JSON data. Whenever the source JSON data changes, it is compared to the local copy of the model. After diffing the two sets of data, the JsonListModel applies all detected changes individually. It thus synchronizes the local copy with the JSON data step-by-step.

The JsonListModel type implements the full QML ListModel API and fires individual events for all changes in the data. The list view can thus only update relevant entries or apply transition animations. This is super useful, as you can e.g. fetch new data and simply replace the old JSON. The JsonListModel will detect all changes, and the ListView updates its items accordingly - without a full redraw.

The JsonListModel is backed by a performant QSyncable model in Qt C++ and exposed to QML for easy usage. With the JsonListModel you can:

  • Fetch JSON data from REST APIs with QML and JavaScript.
  • Pass the data to your C++ list model, which synchronizes the JSON data and prepares it for usage in your view.
  • Show the model data with a list view in QML, which only renders list items that have changed.

With the JsonListModel you do not require to implement a custom model in C++ anymore. The JsonListModel itself is your C++ model, which is fully usable from QML and can work with JSON list items of any format.

Apart from list views, the model also supports the GridView and Repeater types to display model data.

Example Usage

Basic Demo Project

For a simple example project that uses JsonListModel to show data from a REST API, you can see the MVC Architecture Demo App.

Todo List Demo

The advanced ToDo List App supports fetching of todos, creation and storing of drafts, offline caching, paging, sorting and filtering. It uses list tranisition animations and shows how to integrate PullToRefreshHandler, VisibilityRefreshHandler or SortFilterProxyModel.

AppListView with Transition Animation

The following example shows how to use JsonListModel together with AppListView. When adding a new item to the JSON, the JsonListModel detects the change. The AppListView can thus use a transition animation when adding the entry. It is not required to fully redraw the list and exising items in the view are not affected.

 import Felgo
 import QtQuick

 App {
   AppPage {
     id: page

     // property with json data
     property var jsonData: [
       {
         "id": 1,
         "title": "Entry 1"
       },
       {
         "id": 2,
         "title": "Entry 2"
       },
       {
         "id": 3,
         "title": "Entry 3"
       }
     ]

     // list model for json data
     JsonListModel {
       id: jsonModel
       source: page.jsonData
       keyField: "id"
     }

     // list view
     AppListView {
       anchors.fill: parent
       model: jsonModel
       delegate: SimpleRow {
         text: model.title
       }

       // transition animation for adding items
       add: Transition {
         NumberAnimation {
           property: "opacity";
           from: 0;
           to: 1;
           duration: 1000
           easing.type: Easing.OutQuad;
         }
       }
     }

     // Button to add a new entry
     AppButton {
       anchors.horizontalCenter: parent.horizontalCenter
       anchors.bottom: parent.bottom

       text: "Add Entry"
       onClicked: {
         var newItem = {
           "id": jsonModel.count + 1,
           "title": "Entry "+(jsonModel.count + 1)
         }
         page.jsonData.push(newItem)

         // manually emit signal that jsonData property changed
         // JsonListModel thus synchronizes the list with the new jsonData
         page.jsonDataChanged()
       }
     }
   } // Page
 }

To learn about ListView features in general, you can find more examples here: Use ScrollViews and ListViews in Your App.

Sorting, Filtering and List Sections

As the JsonListModel is a regular QML ListModel, it is compatible with SortFilterProxyModel and also supports list sections:

 import Felgo
 import QtQuick

 App {
   AppPage {
     id: page

     // property with json data
     property var jsonData: [
       {
         "id": 1,
         "title": "Apple",
         "type": "Fruit"
       },
       {
         "id": 2,
         "title": "Ham",
         "type": "Meat"
       },
       {
         "id": 3,
         "title": "Bacon",
         "type": "Meat"
       },
       {
         "id": 4,
         "title": "Banana",
         "type": "Fruit"
       }
     ]

     // list model for json data
     JsonListModel {
       id: jsonModel
       source: page.jsonData
       keyField: "id"
       fields: ["id", "title", "type"]
     }

     // SortFilterProxyModel for sorting or filtering lists
     SortFilterProxyModel {
       id: sortedModel
       // Note: when using JsonListModel, the sorters or filter might not be applied correctly when directly assigning sourceModel
       // use the Component.onCompleted handler instead to initialize SortFilterProxyModel
       Component.onCompleted: sourceModel = jsonModel
       sorters: LocaleAwareSorter { id: typeSorter; roleName: "type"; ascendingOrder: true }
     }

     // list view
     AppListView {
       anchors.fill: parent
       model: sortedModel
       delegate: SimpleRow {
         text: model.title
       }
       section.property: "type"
       section.delegate: SimpleSection { }
     }

     // Button change the sorting order
     AppButton {
       anchors.horizontalCenter: parent.horizontalCenter
       anchors.bottom: parent.bottom

       text: "Change Order"
       onClicked: typeSorter.ascendingOrder = !typeSorter.ascendingOrder
     }
   } // Page
 }

To correctly have relevant model roles available for SortFilterProxyModel, make sure to specify all required JsonListModel::fields.

Property Documentation

count : int

Returns the number of list items.


fields : array

Defines the available fields of the model. If not set, the JsonListModel will use the first appended record as reference. You are not able to change the available fields once the model holds data using the given fields.

Example:

 JsonListModel {
     keyField: "id"
     fields: [
         "id",
         "value"
     ]
 }

keyField : string

Sets the key field of the data source. The value in key field should be unique for each entry of the list.

If the key field is not set, JsonListModel won't be able to identify insertion, removal and moving of items.


source : array

JsonListModel is a wrapper for Javascript arrays. Updates to the source property will trigger synchronization of JsonListModel. The list model then emits changes according to the difference of the current and new data set.

Example:

 JsonListModel {
     keyField: "id"

     source: [
         { "id": "a", "value": 1 },
         { "id": "b", "value": 2 }
     ]

     fields: [
         "id",
         "value"
     ]
 }

Method Documentation

void append(var value)

Appends an item at the end of the list.


var get(int index)

Returns the item at the specified index in the model.


int indexOf(string field, var value)

Gets the index of a record that matches the input value for a given field.

If no matching record is found, the function returns -1.


void insert(int index, var item)

Inserts an item at the given index position.


void move(int from, int to, int n)

Moves n items from one position in the model to another.


void remove(int index, int count = 1)

Deletes the content at index from the model. You can specify the number of items to be removed with the count argument.


void set(int index, var changes)

Changes multiple properties for the list entry at the given index position. Properties that are not part of the changes object are left unchanged.

A new item is appended to the list if the index is equal to count. Otherwise, index must match an element in the list.


void setProperty(int index, string property, var value)

Assigns the passed value to a given property of the list item positioned at index. Only the specified property will be set for the item.


[since Felgo 4.0.0] void syncModelToSource()

When the source property changes, the JsonListModel automatically synchronizes to match the new JSON data. Adapting the source JSON data is thus the preferred way for making changes to the model.

Changes done with ListModel methods like append(), insert(), set(), setProperty(), move() or remove() only exist temporary until the next synchronization happens.

If you want to use these methods to make temporary changes, you can call the JsonListModel::syncModelToSource() method to apply your changes back into JsonListModel::source.

This method was introduced in Felgo 4.0.0.


Qt_Technology_Partner_RGB_475 Qt_Service_Partner_RGB_475_padded