NativeScript Core

RadListView Load on Demand

The load-on-demand feature is particularly useful in cases when data needs to be loaded in chunks (pages) to optimize bandwidth usage and improve the UX. The value of the loadOnDemandMode property determines the mode that will be used for loading on demand. It accepts the values from the ListViewLoadOnDemandMode enumeration:

  • Manual - in this mode the user needs to manually request the next data page
  • Auto - in this mode the next data page is automatically requested as the user approaches the end of the scrollable list
  • None - in this mode load on demand is disabled

When more items need to be loaded, RadListView fires the loadMoreDataRequested event. That event will continue to be fired until you set the returnValue of the arguments to false and call the notifyLoadOnDemandFinished(disableLoadOnDemand) with a true parameter, you can use this when you have reached the end of your data stream and there will no longer be any data to be loaded.

In addition, RadListView exposes the loadOnDemandBufferSize property which determines the count of items left to scroll which when reached triggers a loadMoreDataRequested event. This property is used when the load-on-demand mode is set to be Auto.

Handling the loadMoreDataRequested Event

The following code snippet demonstrates how the loadMoreDataRequestedEvent event is handled. We first need to subscribe for the event as the following XML snippet shows:

Example 1: Subscribing for loadMoreDataRequested in XML:

<lv:RadListView id="ls" items="{{ dataItems }}"  row="0" loadOnDemandMode="Manual" loadMoreDataRequested="{{onLoadMoreItemsRequested}}">

in our event handler we make a data request and when the data chunk is ready we feed the list:

Example 2: Handling the loadMoreDataRequested in XML:

public addMoreItemsFromSource(chunkSize: number, listView: RadListView) {
    let newItems = this._sourceDataItems.splice(0, chunkSize);
    this.dataItems.push(newItems);

    if (listView) {
        // Call the optimized function for on-demand loading finished.
        // (with 0 because the ObservableArray has already
        // notified about the inserted items)
        listView.notifyAppendItemsOnDemandFinished(0, this._sourceDataItems.length === 0);
    }
}

public onLoadMoreItemsRequested(args: LoadOnDemandListViewEventData) {
    const that = new WeakRef(this);
    const listView: RadListView = args.object;
    if (this._sourceDataItems.length > 0) {
        setTimeout(function () {
            that.get().addMoreItemsFromSource(20, listView);
        }, 0);
        args.returnValue = true;
    } else {
        args.returnValue = false;
        listView.notifyAppendItemsOnDemandFinished(0, true);
    }
}

Here, the usage of a timer is for the purpose of simulating a call to a remote service. The notifyLoadOnDemandFinished(disableLoadOnDemand) call is made to inform the list view that the requested data chunk has been delivered.

Customizing the Load-on-Demand View

To customize the load-on-demand view displayed at the end of the list you need to use the loadOnDemandItemTemplate property. Here's a simple example:

Example 3: Providing a custom loadOnDemandItemTemplate:

<lv:RadListView.loadOnDemandItemTemplate>
    <GridLayout style="background-color: #7fff7f;" height="44" bottomMargin="20">
         <Label text="Load More" horizontalAlignment="center" verticalAlignment="center"/>
    </GridLayout>
</lv:RadListView.loadOnDemandItemTemplate>

The loadOnDemandItemTemplate property is used just like the itemTemplate property. Note that the binding context of the view generated from this template is the one assigned to the page.

References

Want to see this scenario in action? Check our SDK examples repo on GitHub. You will find this and many other practical examples with NativeScript UI.

Related articles you might find useful: