NativeScript Angular

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.

Example

The following scenario demonstrates how the loadMoreDataRequested event is handled. In addition, an example of a custom load-on-demand view is also given. A custom load-on-demand view is provided via the TKListViewLoadOnDemandDirective which is used with the tkListLoadOnDemandTemplate selector. To feed RadListView with data we use an ObservableArray which provides smart data change notifications to RadListView. When the loadMoreDataRequested event is fired we push new items into the array which notifies the list that a change has occurred.

Example: The Template

The following snippet shows the template used to create the UI for the scenario. It shows how a handler for the loadMoreDataRequested event is provided, as well as how a custom load-on-demand view is applied:

Example: The Component

The following code snippet demonstrates the code behind the template. Here you see how the loadMoreDataRequested event is handled and how data is fed back to RadListView:

<RadListView [items]="dataItems" loadOnDemandMode="Manual" (loadMoreDataRequested)="onLoadMoreItemsRequested($event)">
export class ListViewFixedSizeManualComponent implements OnInit {
    private _dataItems: ObservableArray<DataItem>;
    private _sourceDataItems: ObservableArray<DataItem>;
    private layout: ListViewLinearLayout;

    constructor(private _changeDetectionRef: ChangeDetectorRef) {
    }

    ngOnInit() {
        this.layout = new ListViewLinearLayout();
        this.layout.scrollDirection = ListViewScrollDirection.Vertical;
        this.initDataItems();
        this._changeDetectionRef.detectChanges();
        this._dataItems = new ObservableArray<DataItem>();
        this.addMoreItemsFromSource(6);
    }

    public get dataItems(): ObservableArray<DataItem> {
        return this._dataItems;
    }


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

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

    private initDataItems() {
        this._sourceDataItems = new ObservableArray<DataItem>();
        for (let i = 0; i < posts.names.length; i++) {
            if (androidApplication) {
                this._sourceDataItems.push(new DataItem(i, posts.names[i], "This is item description", posts.titles[i], posts.text[i], "res://" + posts.images[i].toLowerCase()));
            }
            else {
                this._sourceDataItems.push(new DataItem(i, posts.names[i], "This is item description", posts.titles[i], posts.text[i], "res://" + posts.images[i]));
            }
        }
    }
}