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 130 131 132 133 134 135 136 | 3x 3x 3x 3x 18x 18x 18x 18x 18x 18x 18x 18x 18x 5x 5x 1x 1x 1x 1x 1x 1x 1x 1x 1x | import {
AfterViewInit,
ChangeDetectorRef,
Component,
ComponentRef,
ContentChild,
ElementRef,
EventEmitter,
Output,
Renderer2,
TemplateRef,
ViewChild,
ViewContainerRef
} from '@angular/core';
import { DynamicComponentService } from '../../ngui-utils/src/dynamic-component.service';
import { NguiInviewPageComponent } from './ngui-inview-page.component';
/**
* Virtual List
*
* The `<ngui-inview ..>` inserts <ngui-inview-page> into
* `<div #pages>` when it is in viewport
* When it's inserted, it will be pushed down, which makes it out of viewport.
* User scrolls down to see the bottom of the list,
* then it will insert another `<ngui-inview-page>` again.
*
* <ngui-inview-page> listens to (nguiInview) and (nguiOutview) events,
* when <ngui-inview-page> is out of view port, it empties out the contents.
* and it restores back the contents when it is in viewport again.
### Example
```html
<ngui-virtual-list (bottomInview)="loadItems($event)">
<ng-template let-items="items">
<div *ngIf="!items">Loading</div>
<li *ngFor="let num of items; trackBy: num">row number: {{ num }}</li>
</ng-template>
</ngui-virtual-list>
```
*/
@Component({
selector: 'ngui-virtual-list',
template: `
<div class="ngui-virtual-list"
(focus)="_focused = true"
(click)="_focused = true">
<!-- hold multiple <ngui-inview-page> -->
<div #pages></div>
<!-- insert <ngui-inview-page> into #pages -->
</div>
<ngui-inview (inview)="addAnInviewPageToPages()"></ngui-inview>
`,
styles: [`
:host {display: block}
`]
})
export class NguiVirtualListComponent implements AfterViewInit {
/** the container NguiInviewPage will be inserted */
@ViewChild('pages', { read: ViewContainerRef }) pagesRef: ViewContainerRef;
/** Template of NguiInviewPage. Allow users to define their own template */
@ContentChild(TemplateRef) template: TemplateRef<any>;
/** Fired when child `<ngui-list-item>` is selected */
@Output() selected: EventEmitter<any> = new EventEmitter();
/** Fired when `ESC` key is pressed from `<ngui-list-item>` */
@Output() escaped: EventEmitter<any> = new EventEmitter();
/**
* Event fired when bottom of the virtual list is in view
* The handler of this event must call `$event.addItems(items: Array<any>)` to fill contents
* If not, only the first page is loaded, and rest of the pages won't be loaded;
### Example
```html
<ngui-virtual-list (bottomInview)="loadItems($event)">
<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 #noItems>Loading</ng-template>
</ng-template>
</ngui-virtual-list>
```
*/
@Output() bottomInview: EventEmitter<any> = new EventEmitter();
/** The last NguiInviewPageComponent being inserted */
inviewPage: ComponentRef<NguiInviewPageComponent>;
_focused = false;
/** Indicates if a page is still loading */
isListLoading: boolean;
inviewPages: Array<ComponentRef<NguiInviewPageComponent>> = [];
constructor(
public renderer: Renderer2,
public element: ElementRef,
public dynamicComponentService: DynamicComponentService,
public cdr: ChangeDetectorRef
) {}
/** Check if necessary input and output is provided */
ngAfterViewInit(): void {
if (!this.template || !this.bottomInview.observers.length) {
console.error('<ngui-virtual-list> requires [template] and {bottomInview)');
}
}
/**
* When the bottom is inview port, this function is called
* It will insert a dynamicall created NguiInviewPageComponent with the given template.
* It will also fires (bottomInview) event, so that user can fill up items for the page.
*/
addAnInviewPageToPages(): void {
if (!this.isListLoading) {
this.isListLoading = true;
this.inviewPage =
this.dynamicComponentService.createComponent(NguiInviewPageComponent, this.pagesRef);
this.dynamicComponentService.insertComponent(this.inviewPage);
this.inviewPage.instance.template = this.template;
this.inviewPages.push(this.inviewPage);
this.bottomInview.emit(this); // fire event, so that user can load items
}
}
// set items of NguiInviewPageComponent
addList(items: Array<any>): void {
this.isListLoading = false;
this.inviewPage.instance.setItems(items);
}
}
|