All files / ngui-list/src ngui-inview-page.component.ts

100% Statements 29/29
81.81% Branches 9/11
100% Functions 6/6
100% Lines 27/27

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 1294x                                                                                                       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 &lt;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();
    }
  }
 
}