2

I find different samples for the VirtualScrollViewPort but with all I have the problem how to use them in real life. The samples load the whole data at once from the server - but since they are too large, I wanna load them individually. My main requirements are:

  1. Search mask - user enters some data
  2. Display progress bar...
  3. Query a Search on the server
  4. If no result is found ==> display a message
  5. If something is found ==> display the first n (=10) items
  6. After the user scrolls down and only e.g. 5 items are left ==> load additionally 10 items
    • continue with 5.
    • if only e.g. 3 are left ==> end the scrolling

I tried already the approach from Specifying data section - but there I fail how to recognize that no data is loaded AND I fail to initiate the view - especially when the user resets the content.

I tried as well with

<cdk-virtual-scroll-viewport itemSize="itemHeight" (scrolledIndexChange)="nextBatch($event,(resultList[resultList.length-1].total) )"
class="scroll-container">
  <div *cdkVirtualFor="let search of resultList"  class="card-item" >

which works for the first requirements but finally I fail with scrolledIndexChange is fired only on the very first item on the list. I have no clue how to track if user already is displaying already item 6 (which would load additional data). On the API page I do not see any @Output() beside the scrolledIndexChange.

Any hint how to track the events properly?

UPDATE First problem I figured out was the incorrect syntax of setting the height, i.e. [itemSize]="itemHeight" is the appropriate syntax otherwise it remains always to zero ==> all elements are rendered!

0

1 Answer 1

1

After some work my final solution looks like:

<ng-container *ngIf="lstSearchResults|async as resultList; else searching">
    <cdk-virtual-scroll-viewport [itemSize]="itemHeight" (scrolledIndexChange)="nextBatch()"
         class="scroll-container">
       <div *cdkVirtualFor="let search of resultList"  class="card-item">

where it is noteworthy that my list is an async list, named lstSearchResults and in the the ts code I have:

// for proper height and caching... (in pixels)
itemHeight = 174;

search(searchConfig: SearchOptions): void {
    //    ....
    this.lstSearchResults = new BehaviorSubject<SearchResult[]>(null);
    // call the REST service
    this.searchService.doSearch(searchConfig).subscribe((foundEntry) => {
        if (!this.resultList) {
            // first list - nothing found up till now
            this.resultList = foundEntry;
        } else {
            if (!this.resultList[this.resultList.length - 1]) {
                //remove the marker (which was added below/previously)
                this.resultList.pop();
            }
            foundEntry.map((item) => this.resultList.push(item));
        }
        if (this.resultList[0] && this.resultList[0].total > this.resultList.length + 1) {
            //some more elements could be fetched from the server ==> add a dummy entry for rendering
            this.resultList.push(undefined);
        }
        // notify the search list to be updated
        this.lstSearchResults.next(this.resultList);
    });
}

and for the scrolling I have the following code:

nextBatch(): void {
    if (this.theEnd) {
        return;
    }

    if (this.resultList[0]) {
        // something was found
        if (
            this.viewport.getRenderedRange().end ===
            this.viewport.getDataLength()
        ) {
            // since we scrolled to the very end of the rendered display
            // ==> check if further search is required (and do so...)
            const searchTotal = this.resultList[0].total;
            this.mySearchConfig.posOffset += this.mySearchConfig.noOfElements;
            // some basic check if the total counter exceeds the current offset
            // i.e. no further search required
            if (this.mySearchConfig.posOffset <= searchTotal) {
                this.search(this.mySearchConfig, true);
            } else {
                this.theEnd = true;
            }
        }
    } else {
        // nothing found ==> mark the end
        this.theEnd = true;
    }
}

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.