We have created multiple arrays named with ELEMENT_DATA in which we have stored data like serial_no, name, weight, and height. Then we have used mat table to display the data through the getData() method like the following code:
App.component.ts
import { Component, OnInit, ViewChild } from '@angular/core';
import { Sort, MatSort, MatTableDataSource } from '@angular/material';
import { noop as _noop } from 'lodash-es';
interface Element {
name: string;
serial_no: number;
weight: number;
height: number;
}
const ELEMENT_DATA: Element[] = [
{serial_no: 1, name: 'Bunty', weight: 50, height: 5.1},
{serial_no: 2, name: 'Gaurav', weight: 52, height: 5.2},
{serial_no: 3, name: 'Jayraj', weight: 69, height: 5.5},
{serial_no: 4, name: 'Lokesh', weight: 90, height: 6},
{serial_no: 5, name: 'Hardik', weight: 41, height: 5},
{serial_no: 6, name: 'Sunil', weight: 27, height: 6},
{serial_no: 7, name: 'Aniket', weight: 45, height: 4.5},
{serial_no: 8, name: 'Jignesh', weight: 94, height: 6},
{serial_no: 9, name: 'Abdul', weight: 84, height: 5},
{serial_no: 10, name: 'James', weight: 29, height: 4},
{serial_no: 11, name: 'Jigar', weight: 56, height: 5.1},
{serial_no: 12, name: 'Jaimin', weight: 35, height: 5},
{serial_no: 13, name: 'Nitin', weight: 68, height: 5.5},
{serial_no: 14, name: 'Suhani', weight: 85, height: 3.5},
{serial_no: 16, name: 'Lalit', weight: 36, height: 4},
{serial_no: 17, name: 'Hiren', weight: 53, height: 4.5},
{serial_no: 18, name: 'Himanshu', weight: 48, height: 4},
{serial_no: 19, name: 'Piyush', weight: 93, height: 5},
{serial_no: 20, name: 'Keval', weight: 78, height: 5.2},
];
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent implements OnInit {
dataSource: MatTableDataSource;
limit: number = 1000;
displayedColumns: string[] = ['serial_no', 'name', 'weight', 'height'];
full: boolean = true;
@ViewChild(MatSort) sort: MatSort;
constructor() { }
ngOnInit() {
this.getData();
}
handleScroll = (scrolled: boolean) => {
console.timeEnd('lastScrolled');
scrolled ? this.getData() : _noop();
console.time('lastScrolled');
}
hasMore = () => !this.dataSource || this.dataSource.data.length < this.limit;
getData() {
const data: Element[] = this.dataSource
? [...this.dataSource.data, ...ELEMENT_DATA]
: ELEMENT_DATA;
this.dataSource = new MatTableDataSource(data);
this.dataSource.sort = this.sort;
}
}
In our scroll-component we have created the methods to implement infinite scrolling, in these, we have provided some properties to an item to function with scrolling like the following:
-
infiniteScroll is the primary property that defines the content that is scrolling through.
-
infiniteScrollDistance is Used to provide the distance where we will reach the defined percentage of the item, at which time the scrolling event will be triggered.
-
infinteScrollThrottle indicates the number of milliseconds after the scrolling event will be triggered.
-
Scrolled is a method for carrying out a specific action when scrolling is reached.
-
In scrollWindow, we should decide if we want to listen to the window scroll or scroll event.
So, these are some of the properties we used in this demonstration project, but we can use more methods or properties depending on our requirements.
So, our code main to implement infinite scrolling is in our scroll-container like the following:
Scroll-container.component.ts
import { Component, OnInit, OnChanges, Input, Output, EventEmitter, HostListener, ElementRef } from '@angular/core';
import { throttle as _throttle, noop as _noop } from "lodash-es";
enum ScrollDirection {
UP = 'up',
DOWN = 'down'
}
enum ScrollListener {
HOST = 'scroll',
WINDOW = 'window:scroll'
}
@Component({
selector: 'app-scroll-container',
templateUrl: './scroll-container.component.html',
styleUrls: ['./scroll-container.component.css']
})
export class ScrollContainerComponent implements OnInit, OnChanges {
private _element: Element;
private _window: Element;
public scrollTop = 0;
@Input() more = true;
@Input() scrollDelay = 500;
@Input() scrollOffset = 1000;
@Output() scrolled: EventEmitter = new EventEmitter();
@HostListener(ScrollListener.HOST) _scroll: Function;
@HostListener(ScrollListener.WINDOW) _windowScroll: Function;
constructor(private elRef: ElementRef) {
this._element = this.elRef.nativeElement;
this._window = document.documentElement as Element;
}
ngOnInit() {
this.setThrottle();
}
ngOnChanges(changes) {
if (changes.scrollDelay) this.setThrottle();
}
setThrottle() {
this._scroll = this._windowScroll = _throttle(this.handleScroll, this.scrollDelay);
}
getListener = () => this.elRef.nativeElement.clientHeight === this.elRef.nativeElement.scrollHeight
? ScrollListener.WINDOW
: ScrollListener.HOST
roundTo = (from: number, to: number = this.scrollOffset) => Math.floor(from / to) * to;
getScrollDirection = (st: number) => this.scrollTop <= st ? ScrollDirection.DOWN : ScrollDirection.UP;
canScroll(e: Element): boolean {
const scrolled = this.more
&& this.getScrollDirection(e.scrollTop) === ScrollDirection.DOWN
&& this.roundTo(e.clientHeight) === this.roundTo(e.scrollHeight - e.scrollTop);
this.scrollTop = e.scrollTop;
return scrolled;
}
handleScroll = () => this.getListener() === ScrollListener.HOST
? this.scrolled.emit( this.canScroll(this._element) )
: this.scrolled.emit( this.canScroll(this._window) )
}
Scroll-container.component.html