Press n or j to go to the next uncovered block, b, p or k for the previous block.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 | 4x 4x 6x 6x 6x 6x 6x 6x 1x 1x 1x 1x 1x 1x 1x 7x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x | import { ChangeDetectorRef, Component, ContentChild, ElementRef, Input, OnDestroy, OnInit, Renderer2, TemplateRef } from '@angular/core'; /** * A block of component that listens to inView and outView events, * so that it empties contents when out of view after backup items * and restores the contents when in view ### Example ```html <ngui-inview-page [items]="items"> <ng-template let-items="items"> <div *ngIf="items else noItems"> <li *ngFor="let num of items; trackBy: num">row number: {{ num }}</li> </div> </ng-template> </ngui-inview-page> ``` */ @Component({ selector: 'ngui-inview-page', template: ` <div class="inview-page contents" [observerOptions]="observerOptions" (nguiInview)="restoreItems()" (nguiOutview)="emptyItems()"> <!-- add blank ngui-list-item by condition --> <!-- no match found ngui-list-item by condition --> <ng-container [ngTemplateOutlet]="template||defaultTemplate" [ngTemplateOutletContext]="{items: items, outView: outView}"> </ng-container> </div> <ng-template #defaultTemplate> <div *ngIf="!items"> Error: requires [items] </div> <div *ngIf="!template"> Error: requires <ng-template></div> </ng-template> `, styles: [` :host {display: block} `] }) export class NguiInviewPageComponent implements OnInit, OnDestroy { /** Allow users to change the contents */ @ContentChild(TemplateRef, {static: true}) template: TemplateRef<any>; // @Input('template') template: TemplateRef<any>; /** List of elements that are used to render this element */ @Input() items: Array<any>; /** IntersectionObserver options */ @Input() observerOptions: IntersectionObserverInit = {threshold: [0, .01]}; /** Indicates that the page of out of viewport */ outView = false; /** The copy of items. This is set when this element is out of viewport */ itemsBackup: Array<any> = []; /** * The first element of this component. * The height of it remains the same even when items get empty out. */ contentsEl: HTMLElement; destroyed: boolean; constructor( private element: ElementRef, private renderer: Renderer2, private cdRef: ChangeDetectorRef ) { } /** * Restore items when in viewport, so that elements are rendered */ restoreItems(): void { if (this.outView) { this.outView = false; this.items = Array.from(this.itemsBackup || []); this.itemsBackup = undefined; this.renderer.setStyle(this.contentsEl, 'height', undefined); this.cdRef.detectChanges(); } } ngOnInit(): void { this.contentsEl = this.element.nativeElement.querySelector('.inview-page.contents'); } ngOnDestroy(): void { this.destroyed = true; } /** * Empty items when not in viewport, so that elements are not rendered */ emptyItems(): void { if (this.items && this.contentsEl && !this.outView) { // set height before emptying contents const height = this.element.nativeElement.getBoundingClientRect().height; this.renderer.setStyle(this.contentsEl, 'height', `${height}px`); this.outView = true; this.itemsBackup = Array.from(this.items || []); this.items = undefined; if (!this.destroyed) { this.cdRef.detectChanges(); } } } setItems(items: Array<any>): void { if (!this.destroyed) { this.items = items; this.cdRef.detectChanges(); } } } |