[SalesForce] LWC: load more with infinite scroll with template iterator or for:each

I know that there is enable-infinite-loading using lightning-datatable, but I need it to work with template iterator or for:each. I need to display each item of the list in an elaborate format, rather than in a simple list.

Has anyone implemented infinite scrolling with template iterator or for:each?

EDIT:

Thank you sfdcfox for providing a good starting point. Here's the solution I went with to avoid the double scrollbars –

HTML:

<template>
    <div class="scrollContainer" onscroll={handleScroll}>
        <table>
            <thead>
                <th>Column 1</th>
                <th>Column 2</th>
            </thead>
            <tbody>
                <template iterator:item={items}>
                    <tr key={item.value.id}>
                        <td>
                            {item.value.name}
                        </td>
                        <td>
                            {item.value.desc}
                        </td>
                    </tr>
                    <template if:true={item.last}>
                        <loadingpos key={item.value.id}>Loading ...</loadingpos>
                    </template>
                </template>
            </tbody>
        </table>
    </div>
</template>

JS:

import { LightningElement, track, api } from 'lwc';

export default class App extends LightningElement {
    @track items = [];
    connectedCallback() {
        let parentThis = this;
        this.items = [];
        let i = 0;
        while(++i < 100) {
            this.items.push( {id:i, name:"Row "+i, desc: "Example Row "+i} );
        }
        window.addEventListener('scroll', function() {
            if ((window.innerHeight + window.scrollY) >= document.body.offsetHeight) {
                let i = 0, t = parentThis.items.length;
                while(++i < 30) {
                    parentThis.items.push( {id:i+t, name:"Row "+(i+t), desc: "Example Row "+(i+t)} );
                }
            }
        });
    }
}

Playground

Any feedback is greatly appreciated.

Best Answer

Before this answer, no, I have not implemented such a feature. However, doing so is pretty trivial, so I decided to write one for you. This is not a full-scale, production-ready code, simply an example to get you started with infinite scrolling in LWC. Please see the Playground I created for this.


HTML:

<template>
    <div class="scrollContainer" onscroll={handleScroll}>
        <div class="scrollArea" >
            <table>
                <thead>
                    <th>Column 1</th>
                    <th>Column 2</th>
                </thead>
                <tbody>
                    <template for:each={items} for:item="item">
                        <tr key={item.id}>
                            <td>
                                {item.name}
                            </td>
                            <td>
                                {item.desc}
                            </td>
                        </tr>
                    </template>
                </tbody>
            </table>
        </div>
    </div>
</template>

CSS:

.scrollContainer {
    max-height: 300px;
    overflow: auto;
    position: relative;
    border: 1px solid black;
}
.scrollArea {
    position: relative;
}

JS:

import { LightningElement, track, api } from 'lwc';

export default class App extends LightningElement {
    @track items = [];
    connectedCallback() {
        this.items = [];
        let i = 0;
        while(++i < 30) {
            this.items.push( {id:i, name:"Row "+i, desc: "Example Row "+i} );
        }
    }
    handleScroll(event) {
        let area = this.template.querySelector('.scrollArea');
        let threshold = 2 * event.target.clientHeight;
        let areaHeight = area.clientHeight;
        let scrollTop = event.target.scrollTop;
        if(areaHeight - threshold < scrollTop) {
            let i = 0, t = this.items.length;
            while(++i < 30) {
                this.items.push( {id:i+t, name:"Row "+(i+t), desc: "Example Row "+(i+t)} );
            }
        }
    }
}

I leave it as an exercise to the reader to implement SLDS and other relevant styles. This is meant only to serve as a demo on how to infinite scroll in LWC.