This is a migrated thread and some comments may be shown as answers.

Displaying Everlive data (with expanded relations) Post a reply

4 Answers 27 Views
General Discussion
This is a migrated thread and some comments may be shown as answers.
This question is locked. New answers and comments are not allowed.
David Weinberg
Top achievements
Rank 2
David Weinberg asked on 29 Jun 2017, 12:23 AM

Hi,

I am creating an app with Kendo UI for 2 and NativeScript via Telerik Platform's AppBuilder. I am using the Telerik Platform as a backend via the Everlive API. Due to having referenced related content types, I am using an expression, which limits the data page size to 50 rows.

I am either displaying via ListView or RadListView. Can anyone help me to enable LoadOnDemand to get the next page of the data when the user scrolls to the bottom of the

TIA,

David

 

 

4 Answers, 1 is accepted

Sort by
0
Nick Iliev
Telerik team
answered on 29 Jun 2017, 11:07 AM
Hello David,

The RadListView comes with out-of-the-box loadOnDemand functionality which you can use to implement to get the next content when the user scrolls to the bottom of the current list. Based on the article above you can also refer to the real example (used in the article) which can be found here.

There are some crucial points ni this example which I am going to cover in the lines below

- first, we are declaring our properties items and _numberOfAddedItems. While items will be used as our source of items the _numberOfAddedItems will be used to keep track on how many items we have currently loaded and then when the user scrolls to the bottom and active the loadOnDemand callback we will download the data based on this counter. The initial value of 0 items will be assigned to the initial data load before the items are added and then we will increase the value with 1 for each item pushed into the source array.

- when all of the above is done we are ready to implement the loadOnDemnad functionality. Notice that there are minor differences in the iOS and Android templates so you will need to provide platform-specific files for both platforms if building for both iOS and Android. 
- The first thing we need to do is to set the loadMode and the loadMoreDataRequested callback. In the linked example the loadMode is manual meaning we have to trigger the load on demand via button or other technique but if you want this to happen when the user scrolls to the bottom just change the loadMode to Auto
e.g.
<lv:RadListView loadOnDemandMode="Auto" loadMoreDataRequested="{{ onLoadMoreItemsRequested }}" />

- the next step is to create our loadMoreDataRequested callback as done here. In the example, we have wrapped all in setTimeout just to mock some server delay which is not needed in a real-life project. What one will need to do is to create the API call and using the property _numberOfAddedItems  to load the new items into the source array. While doing that we need to increase the counter of loaded items, notify the list view that the loading has ended and finally return true value as done here.


Regards,
Nikolay Iliev
Progress Telerik
Did you know that you can open private support tickets which are reviewed and answered within 24h by the same team who built the components? This is available in our UI for NativeScript Pro + Support offering.
0
David Weinberg
Top achievements
Rank 2
answered on 29 Jun 2017, 05:44 PM

Hi Nikolay,

Thank you for your very helpful reply. I also had a reply from Martin (via a support ticket). I have implemented both your suggestions and I am almost there. 

Where I am still stuck is in updating the items with the new data. The first time it loads more data, it gets the next 20 rows but does not add them to the list, instead, it replaces them. The other problem is that after the first load, numberOfAddedItems is 70 but it still seems to load the first 50 rows again.

I am sure I am missing something obvious.

onLoadMoreItemsRequested(args: ListViewEventData) {
    let that = new WeakRef(this);
 
    let numberOfAddedItems: number = that.get()._numberOfAddedItems;
 
    that.get()._service.getNextX(numberOfAddedItems)
        .subscribe(
            (data) => {
                let arr: shared.Item[] = [];
                data.forEach((item) => {
 
                    let newItem: shared.Item = {
                        "id": item.Id,
                        "data": item
                    };
 
                    arr.push(newItem);
                });
 
                that.get()._items$.next([...arr]);
                //alert("_numberOfAddedItems= " + that.get()._numberOfAddedItems + "arr.length= "+arr.length);
 
                that.get()._numberOfAddedItems += arr.length;
                var listView: RadListView = args.object;
                listView.notifyLoadOnDemandFinished();
 
            }, (error) => {
 
                console.log(JSON.stringify(error));
 
            }
        );
 
}

Note that in the AppBuilder generated code  _items$ is of type BehaviorSubject<Item[]> and items are added via _items$.next().

getNextX(start: number): Observable<any> {
    //alert("getNextX("+start+")");
    let promise: Promise<any> = new Promise(
        (resolve, reject) => {
            //alert(start);
            let query = this._provider.query;
            query.skip(start).take(20);
            this._data
                .expand(this._expandExpression)
                .get(query)
                .then(data => resolve(data.result || []))
                .catch(error => reject(error));
        }
    );
 
    return Observable.fromPromise(promise);
}

 

Thanks,

David

0
Accepted
Nick Iliev
Telerik team
answered on 30 Jun 2017, 07:25 AM
Hello David,

Thank you for the snippets and for the descriptive information! I have researched your code and what is happening is that you are creating a new empty array on each call of the onLoadMoreItemsRequested method. As this is called when the users trigger loadMoreData event this is erasing your initial items and pushing your new items to the emptied array instead of adding them.

Line where the array is reset
let arr: shared.Item[] = [];

What you can do to resolve this is to create your observable property (in our example called dataItems) and give its initial empty value in a init method for example as done here. Then in your onLoadMoreItemsRequested method, you can access this array and without resetting it to simply push the new items needed with your API call.

Now, I was not able to fully reproduce your code in working state as I do not have an API access with the used queris but still I suspect that both of you issue are closely related. Let me know if caching the source array in an observable property has resolved these problems for your case.

As a side note, I noticed that you are most likely using Angular based application. We have a very thorough tutorial that covers all aspect of creating an application with NativeScript and Angular here and you can use the full source code of the application as a reference on how to work with source array with an initial value and with a BehavourSubject (which in the context of this app is used for various scenarios including publishing newly created items).

Regards,
Nikolay Iliev
Progress Telerik
Did you know that you can open private support tickets which are reviewed and answered within 24h by the same team who built the components? This is available in our UI for NativeScript Pro + Support offering.
0
David Weinberg
Top achievements
Rank 2
answered on 05 Jul 2017, 04:54 PM

Hi Nikolay,

I have loadOnDemand functionality working. The issue was that after I switched to a reusing an array, the list would jump to the top on each extra load of data. This it seems is because RadListView does not work as expected with a BehaviorSubject when new items are added to the array.

I was advised by support to change from BehaviorSubject to ObservableArray and it now works correctly. I am able to scroll to the bottom of a list of 1750 rows without any problems.

If anyone else is facing similar issues, let me know and I will share the code.

David

Tags
General Discussion
Asked by
David Weinberg
Top achievements
Rank 2
Answers by
Nick Iliev
Telerik team
David Weinberg
Top achievements
Rank 2
Share this question
or