├── .gitignore
├── CHANGELOG.md
├── README.md
├── dist
├── lazyFor.directive.d.ts
├── lazyFor.directive.js
├── lazyFor.directive.metadata.json
├── lazyFor.module.d.ts
├── lazyFor.module.js
└── lazyFor.module.metadata.json
├── package.json
├── src
├── lazyFor.directive.ts
└── lazyFor.module.ts
└── tsconfig.json
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | .idea
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Change Log
2 |
3 | ## 1.1.5 - 2017-10-31
4 | - Fixed issue that would occur if the list started out being empty
5 |
6 | ## 1.1.4 - 2017-10-20
7 | - Fixed issue with clearing large list of items
8 |
9 | ## 1.1.3 - 2017-04-24
10 | - Added check to only regenerate DOM elements if items in the list have changed or a scroll event has fired. This greatly improves performance in some cases.
11 | - Added this change log
12 |
13 | ## 1.1.2 - 2017-04-21
14 | - Fixed bug that occurred when the container element is not a direct parent of the element with `lazyFor` on it
15 |
16 | ## 1.1.1 - 2017-04-21
17 | - Fixed issue with uninitialized lists
18 |
19 | ## 1.1.0 - 2017-04-21
20 | - Added local variable named index that can be used to determine the index of the current item. e.g.:
21 | ```HTML
22 |
23 | {{items}} {{i}}
24 |
25 | ```
26 |
27 | ## 1.0.0 - 2017-04-19
28 | - Initial release
29 | - Added all the things
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # lazyFor
2 |
3 | `lazyFor` is an Angular 2+ directive that can be used in place of `ngFor`. The main difference is that `lazyFor` will only render items when they are visible in the parent element. So as a user scrolls, items that are no longer visible will be removed from the DOM and new items will be rendered to the DOM.
4 |
5 | ## Sample Usage
6 | ### [Plunker Demo](https://embed.plnkr.co/t9OKzEOObBClzI6MX6uo/?show=app.component.ts,preview)
7 |
8 | Install with `npm install --save angular-lazy-for`
9 |
10 | *app.module.ts*
11 | ```TypeScript
12 | import {NgModule} from '@angular/core';
13 | import {LazyForModule} from 'angular-lazy-for';
14 |
15 | @NgModule({
16 | declarations: [/*...*/],
17 | imports: [
18 | //...
19 | LazyForModule
20 | ],
21 | providers: [/*...*/],
22 | bootstrap: [/*...*/]
23 | })
24 | export class AppModule {
25 | }
26 | ```
27 |
28 | *Template Input*
29 | ```html
30 |
31 | -
32 | {{item}}
33 |
34 |
35 | ```
36 |
37 | *DOM Output*
38 | ```html
39 |
40 |
41 | - 3
42 | - 4
43 | - 5
44 |
45 |
46 | ```
47 |
48 | ## When to use `lazyFor`
49 | * When you know the size of the iterable and you only want to create DOM elements for visible items
50 | * Fix performance issues with page load time
51 | * Fix change detection performance issues
52 |
53 | ## When *not* to use `lazyFor`
54 | * Not meant to replace `ngFor` in all cases. Only use `lazyFor` if you have performance issues
55 | * Not an infinite scroll. don't use it if you don't know the total size of the list
56 | * Doesn't currently support loading items asynchronously. Although support for this may be added in the future
57 | * This directive does some DOM manipulation so it won't work if your Angular app runs in a web worker or if you use Angular Universal
58 |
59 | ## Performance
60 | `lazyFor` can improve performance by preventing unnecessary content from being rendered to the DOM. This also leads to fewer bindings which reduces the load on change detection. Using `ngFor` is usually very fast but here is a casae where it has a noticeable performance impact:
61 |
62 | ### [Plunker Performance Demo](https://embed.plnkr.co/eRMjnhW1ctU1VwdRhE8x/?show=app.component.ts,preview)
63 |
64 | ## Optional Parameters
65 |
66 | ### withHeight
67 | This directive will try to figure out the height of each element and use that number to calculate the amount of spacing above and below the items. If you are having issues with the defualt behaviour you can specify an explicit height in pixels.
68 |
69 | ```HTML
70 |
71 | ```
72 |
73 | ### inContainer
74 | `lazyFor` needs to know which element is the scrollable container the items will be inside of. By default it will use the parent element but if this is not the right element you can explicitly specify the container.
75 |
76 | ```HTML
77 |
82 | ```
83 |
84 | ### withTagName
85 | This directive works by creating an empty element above and below the repeated items with a set height. By default these buffer elements will the use the same type of tag that `lazyFor` is on. However you can specify a custom tag name with this parameter if needed.
86 |
87 | *Template*
88 | ```HTML
89 |
90 |
91 |
92 | ```
93 |
94 | *DOM Output*
95 | ```HTML
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 | ```
--------------------------------------------------------------------------------
/dist/lazyFor.directive.d.ts:
--------------------------------------------------------------------------------
1 | import { ViewContainerRef, TemplateRef, DoCheck, IterableDiffers } from '@angular/core';
2 | export declare class LazyForDirective implements DoCheck {
3 | private vcr;
4 | private tpl;
5 | private iterableDiffers;
6 | itemHeight: number;
7 | containerElem: HTMLElement;
8 | itemTagName: string;
9 | lazyForOf: any;
10 | private templateElem;
11 | private beforeListElem;
12 | private afterListElem;
13 | private list;
14 | private initialized;
15 | private firstUpdate;
16 | private differ;
17 | private lastChangeTriggeredByScroll;
18 | constructor(vcr: ViewContainerRef, tpl: TemplateRef, iterableDiffers: IterableDiffers);
19 | ngOnInit(): void;
20 | ngDoCheck(): void;
21 | private update();
22 | private onFirstUpdate();
23 | private limitToRange(num, min, max);
24 | }
25 |
--------------------------------------------------------------------------------
/dist/lazyFor.directive.js:
--------------------------------------------------------------------------------
1 | import { Input, Directive, ViewContainerRef, TemplateRef, IterableDiffers } from '@angular/core';
2 | var LazyForDirective = /** @class */ (function () {
3 | function LazyForDirective(vcr, tpl, iterableDiffers) {
4 | this.vcr = vcr;
5 | this.tpl = tpl;
6 | this.iterableDiffers = iterableDiffers;
7 | this.list = [];
8 | this.initialized = false;
9 | this.firstUpdate = true;
10 | this.lastChangeTriggeredByScroll = false;
11 | }
12 | Object.defineProperty(LazyForDirective.prototype, "lazyForOf", {
13 | set: function (list) {
14 | this.list = list;
15 | if (list) {
16 | this.differ = this.iterableDiffers.find(list).create();
17 | if (this.initialized) {
18 | this.update();
19 | }
20 | }
21 | },
22 | enumerable: true,
23 | configurable: true
24 | });
25 | LazyForDirective.prototype.ngOnInit = function () {
26 | var _this = this;
27 | this.templateElem = this.vcr.element.nativeElement;
28 | if (this.containerElem === undefined) {
29 | this.containerElem = this.templateElem.parentElement;
30 | }
31 | //Adding an event listener will trigger ngDoCheck whenever the event fires so we don't actually need to call
32 | //update here.
33 | this.containerElem.addEventListener('scroll', function (e) {
34 | _this.lastChangeTriggeredByScroll = true;
35 | });
36 | this.initialized = true;
37 | };
38 | LazyForDirective.prototype.ngDoCheck = function () {
39 | if (this.differ && Array.isArray(this.list)) {
40 | if (this.lastChangeTriggeredByScroll) {
41 | this.update();
42 | this.lastChangeTriggeredByScroll = false;
43 | }
44 | else {
45 | var changes = this.differ.diff(this.list);
46 | if (changes !== null) {
47 | this.update();
48 | }
49 | }
50 | }
51 | };
52 | //Preconditions:
53 | // this.list is an array
54 | LazyForDirective.prototype.update = function () {
55 | //Can't run the first update unless there is an element in the list
56 | if (this.list.length === 0) {
57 | this.vcr.clear();
58 | if (!this.firstUpdate) {
59 | this.beforeListElem.style.height = "0";
60 | this.afterListElem.style.height = "0";
61 | }
62 | return;
63 | }
64 | if (this.firstUpdate) {
65 | this.onFirstUpdate();
66 | }
67 | var listHeight = this.containerElem.clientHeight;
68 | var scrollTop = this.containerElem.scrollTop;
69 | //The height of anything inside the container but above the lazyFor content;
70 | var fixedHeaderHeight = (this.beforeListElem.getBoundingClientRect().top - this.beforeListElem.scrollTop) -
71 | (this.containerElem.getBoundingClientRect().top - this.containerElem.scrollTop);
72 | //This needs to run after the scrollTop is retrieved.
73 | this.vcr.clear();
74 | var listStartI = Math.floor((scrollTop - fixedHeaderHeight) / this.itemHeight);
75 | listStartI = this.limitToRange(listStartI, 0, this.list.length);
76 | var listEndI = Math.ceil((scrollTop - fixedHeaderHeight + listHeight) / this.itemHeight);
77 | listEndI = this.limitToRange(listEndI, -1, this.list.length - 1);
78 | for (var i = listStartI; i <= listEndI; i++) {
79 | this.vcr.createEmbeddedView(this.tpl, {
80 | $implicit: this.list[i],
81 | index: i
82 | });
83 | }
84 | this.beforeListElem.style.height = listStartI * this.itemHeight + "px";
85 | this.afterListElem.style.height = (this.list.length - listEndI - 1) * this.itemHeight + "px";
86 | };
87 | LazyForDirective.prototype.onFirstUpdate = function () {
88 | var sampleItemElem;
89 | if (this.itemHeight === undefined || this.itemTagName === undefined) {
90 | this.vcr.createEmbeddedView(this.tpl, {
91 | $implicit: this.list[0],
92 | index: 0
93 | });
94 | sampleItemElem = this.templateElem.nextSibling;
95 | }
96 | if (this.itemHeight === undefined) {
97 | this.itemHeight = sampleItemElem.clientHeight;
98 | }
99 | if (this.itemTagName === undefined) {
100 | this.itemTagName = sampleItemElem.tagName;
101 | }
102 | this.beforeListElem = document.createElement(this.itemTagName);
103 | this.templateElem.parentElement.insertBefore(this.beforeListElem, this.templateElem);
104 | this.afterListElem = document.createElement(this.itemTagName);
105 | //This inserts after the templateElem. see http://stackoverflow.com/a/4793630/373655 for details
106 | this.templateElem.parentElement.insertBefore(this.afterListElem, this.templateElem.nextSibling);
107 | if (this.itemTagName.toLowerCase() === 'li') {
108 | this.beforeListElem.style.listStyleType = 'none';
109 | this.afterListElem.style.listStyleType = 'none';
110 | }
111 | this.firstUpdate = false;
112 | };
113 | LazyForDirective.prototype.limitToRange = function (num, min, max) {
114 | return Math.max(Math.min(num, max), min);
115 | };
116 | LazyForDirective.decorators = [
117 | { type: Directive, args: [{
118 | selector: '[lazyFor]'
119 | },] },
120 | ];
121 | /** @nocollapse */
122 | LazyForDirective.ctorParameters = function () { return [
123 | { type: ViewContainerRef, },
124 | { type: TemplateRef, },
125 | { type: IterableDiffers, },
126 | ]; };
127 | LazyForDirective.propDecorators = {
128 | 'itemHeight': [{ type: Input, args: ['lazyForWithHeight',] },],
129 | 'containerElem': [{ type: Input, args: ['lazyForInContainer',] },],
130 | 'itemTagName': [{ type: Input, args: ['lazyForWithTagName',] },],
131 | 'lazyForOf': [{ type: Input },],
132 | };
133 | return LazyForDirective;
134 | }());
135 | export { LazyForDirective };
136 |
--------------------------------------------------------------------------------
/dist/lazyFor.directive.metadata.json:
--------------------------------------------------------------------------------
1 | [{"__symbolic":"module","version":3,"metadata":{"LazyForDirective":{"__symbolic":"class","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Directive"},"arguments":[{"selector":"[lazyFor]"}]}],"members":{"itemHeight":[{"__symbolic":"property","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Input"},"arguments":["lazyForWithHeight"]}]}],"containerElem":[{"__symbolic":"property","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Input"},"arguments":["lazyForInContainer"]}]}],"itemTagName":[{"__symbolic":"property","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Input"},"arguments":["lazyForWithTagName"]}]}],"lazyForOf":[{"__symbolic":"property","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Input"}}]}],"__ctor__":[{"__symbolic":"constructor","parameters":[{"__symbolic":"reference","module":"@angular/core","name":"ViewContainerRef"},{"__symbolic":"reference","module":"@angular/core","name":"TemplateRef","arguments":[{"__symbolic":"reference","name":"any"}]},{"__symbolic":"reference","module":"@angular/core","name":"IterableDiffers"}]}],"ngOnInit":[{"__symbolic":"method"}],"ngDoCheck":[{"__symbolic":"method"}],"update":[{"__symbolic":"method"}],"onFirstUpdate":[{"__symbolic":"method"}],"limitToRange":[{"__symbolic":"method"}]}}}},{"__symbolic":"module","version":1,"metadata":{"LazyForDirective":{"__symbolic":"class","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Directive"},"arguments":[{"selector":"[lazyFor]"}]}],"members":{"itemHeight":[{"__symbolic":"property","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Input"},"arguments":["lazyForWithHeight"]}]}],"containerElem":[{"__symbolic":"property","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Input"},"arguments":["lazyForInContainer"]}]}],"itemTagName":[{"__symbolic":"property","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Input"},"arguments":["lazyForWithTagName"]}]}],"lazyForOf":[{"__symbolic":"property","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Input"}}]}],"__ctor__":[{"__symbolic":"constructor","parameters":[{"__symbolic":"reference","module":"@angular/core","name":"ViewContainerRef"},{"__symbolic":"reference","module":"@angular/core","name":"TemplateRef","arguments":[{"__symbolic":"reference","name":"any"}]},{"__symbolic":"reference","module":"@angular/core","name":"IterableDiffers"}]}],"ngOnInit":[{"__symbolic":"method"}],"ngDoCheck":[{"__symbolic":"method"}],"update":[{"__symbolic":"method"}],"onFirstUpdate":[{"__symbolic":"method"}],"limitToRange":[{"__symbolic":"method"}]}}}}]
--------------------------------------------------------------------------------
/dist/lazyFor.module.d.ts:
--------------------------------------------------------------------------------
1 | import { LazyForDirective } from './lazyFor.directive';
2 | export declare class LazyForModule {
3 | }
4 | export { LazyForDirective };
5 |
--------------------------------------------------------------------------------
/dist/lazyFor.module.js:
--------------------------------------------------------------------------------
1 | import { NgModule } from '@angular/core';
2 | import { LazyForDirective } from './lazyFor.directive';
3 | var LazyForModule = /** @class */ (function () {
4 | function LazyForModule() {
5 | }
6 | LazyForModule.decorators = [
7 | { type: NgModule, args: [{
8 | declarations: [LazyForDirective],
9 | exports: [LazyForDirective]
10 | },] },
11 | ];
12 | /** @nocollapse */
13 | LazyForModule.ctorParameters = function () { return []; };
14 | return LazyForModule;
15 | }());
16 | export { LazyForModule };
17 | export { LazyForDirective };
18 |
--------------------------------------------------------------------------------
/dist/lazyFor.module.metadata.json:
--------------------------------------------------------------------------------
1 | [{"__symbolic":"module","version":3,"metadata":{"LazyForModule":{"__symbolic":"class","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"NgModule"},"arguments":[{"declarations":[{"__symbolic":"reference","module":"./lazyFor.directive","name":"LazyForDirective"}],"exports":[{"__symbolic":"reference","module":"./lazyFor.directive","name":"LazyForDirective"}]}]}]},"LazyForDirective":{"__symbolic":"reference","module":"./lazyFor.directive","name":"LazyForDirective"}}},{"__symbolic":"module","version":1,"metadata":{"LazyForModule":{"__symbolic":"class","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"NgModule"},"arguments":[{"declarations":[{"__symbolic":"reference","module":"./lazyFor.directive","name":"LazyForDirective"}],"exports":[{"__symbolic":"reference","module":"./lazyFor.directive","name":"LazyForDirective"}]}]}]},"LazyForDirective":{"__symbolic":"reference","module":"./lazyFor.directive","name":"LazyForDirective"}}}]
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "angular-lazy-for",
3 | "version": "1.1.5",
4 | "description": "Similar to ngFor but only renders items that are visible.",
5 | "author": "Rob McDiarmid",
6 | "license": "MIT",
7 | "module": "dist/lazyFor.module.js",
8 | "es2015": "dist/lazyFor.module.js",
9 | "typings": "dist/lazyFor.module.js",
10 | "scripts": {
11 | "build": "rimraf dist && ngc -p tsconfig.json"
12 | },
13 | "repository": {
14 | "type": "git",
15 | "url": "https://github.com/robianmcd/angular-lazy-for.git"
16 | },
17 | "devDependencies": {
18 | "@angular/compiler": "^4.0.1",
19 | "@angular/compiler-cli": "^4.0.1",
20 | "@angular/core": "^4.0.1",
21 | "rimraf": "^2.6.1",
22 | "rollup": "^0.41.6",
23 | "rxjs": "^5.3.0",
24 | "typescript": "^2.2.2",
25 | "zone.js": "^0.8.5"
26 | },
27 | "peerDependencies": {
28 | "@angular/core": "^4.0.1",
29 | "rxjs": "^5.3.0",
30 | "zone.js": "^0.8.5"
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/lazyFor.directive.ts:
--------------------------------------------------------------------------------
1 | import {
2 | Input, Directive, ViewContainerRef, TemplateRef, DoCheck, IterableDiffers, IterableDiffer
3 | } from '@angular/core';
4 |
5 | @Directive({
6 | selector: '[lazyFor]'
7 | })
8 | export class LazyForDirective implements DoCheck {
9 | @Input('lazyForWithHeight') itemHeight: number;
10 | @Input('lazyForInContainer') containerElem: HTMLElement;
11 | @Input('lazyForWithTagName') itemTagName: string;
12 |
13 | @Input()
14 | set lazyForOf(list) {
15 | this.list = list;
16 |
17 | if (list) {
18 | this.differ = this.iterableDiffers.find(list).create();
19 |
20 | if (this.initialized) {
21 | this.update();
22 | }
23 | }
24 | }
25 |
26 | private templateElem: HTMLElement;
27 |
28 | private beforeListElem: HTMLElement;
29 | private afterListElem: HTMLElement;
30 |
31 | private list = [];
32 |
33 | private initialized = false;
34 | private firstUpdate = true;
35 |
36 | private differ: IterableDiffer;
37 |
38 | private lastChangeTriggeredByScroll = false;
39 |
40 | constructor(
41 | private vcr: ViewContainerRef,
42 | private tpl: TemplateRef,
43 | private iterableDiffers: IterableDiffers
44 | ) {
45 |
46 | }
47 |
48 | ngOnInit() {
49 | this.templateElem = this.vcr.element.nativeElement;
50 |
51 | if (this.containerElem === undefined) {
52 | this.containerElem = this.templateElem.parentElement;
53 | }
54 |
55 | //Adding an event listener will trigger ngDoCheck whenever the event fires so we don't actually need to call
56 | //update here.
57 | this.containerElem.addEventListener('scroll', (e) => {
58 | this.lastChangeTriggeredByScroll = true;
59 | });
60 |
61 | this.initialized = true;
62 | }
63 |
64 | ngDoCheck() {
65 | if(this.differ && Array.isArray(this.list)) {
66 | if(this.lastChangeTriggeredByScroll) {
67 | this.update();
68 | this.lastChangeTriggeredByScroll = false;
69 | } else {
70 | let changes = this.differ.diff(this.list);
71 |
72 | if(changes !== null) {
73 | this.update();
74 | }
75 |
76 | }
77 | }
78 |
79 | }
80 |
81 | //Preconditions:
82 | // this.list is an array
83 | private update() {
84 | //Can't run the first update unless there is an element in the list
85 | if (this.list.length === 0) {
86 | this.vcr.clear();
87 | if(!this.firstUpdate) {
88 | this.beforeListElem.style.height = "0";
89 | this.afterListElem.style.height = "0";
90 | }
91 | return;
92 | }
93 |
94 | if (this.firstUpdate) {
95 | this.onFirstUpdate();
96 | }
97 |
98 | let listHeight = this.containerElem.clientHeight;
99 | let scrollTop = this.containerElem.scrollTop;
100 |
101 | //The height of anything inside the container but above the lazyFor content;
102 | let fixedHeaderHeight =
103 | (this.beforeListElem.getBoundingClientRect().top - this.beforeListElem.scrollTop) -
104 | (this.containerElem.getBoundingClientRect().top - this.containerElem.scrollTop);
105 |
106 | //This needs to run after the scrollTop is retrieved.
107 | this.vcr.clear();
108 |
109 | let listStartI = Math.floor((scrollTop - fixedHeaderHeight) / this.itemHeight);
110 | listStartI = this.limitToRange(listStartI, 0, this.list.length);
111 |
112 | let listEndI = Math.ceil((scrollTop - fixedHeaderHeight + listHeight) / this.itemHeight);
113 | listEndI = this.limitToRange(listEndI, -1, this.list.length - 1);
114 |
115 | for (let i = listStartI; i <= listEndI; i++) {
116 | this.vcr.createEmbeddedView(this.tpl, {
117 | $implicit: this.list[i],
118 | index: i
119 | });
120 | }
121 |
122 | this.beforeListElem.style.height = `${listStartI * this.itemHeight}px`;
123 | this.afterListElem.style.height = `${(this.list.length - listEndI - 1) * this.itemHeight}px`;
124 | }
125 |
126 | private onFirstUpdate() {
127 | let sampleItemElem: HTMLElement;
128 | if (this.itemHeight === undefined || this.itemTagName === undefined) {
129 | this.vcr.createEmbeddedView(this.tpl, {
130 | $implicit: this.list[0],
131 | index: 0
132 | });
133 | sampleItemElem = this.templateElem.nextSibling;
134 | }
135 |
136 | if (this.itemHeight === undefined) {
137 | this.itemHeight = sampleItemElem.clientHeight;
138 | }
139 |
140 | if (this.itemTagName === undefined) {
141 |
142 | this.itemTagName = sampleItemElem.tagName;
143 | }
144 |
145 | this.beforeListElem = document.createElement(this.itemTagName);
146 | this.templateElem.parentElement.insertBefore(this.beforeListElem, this.templateElem);
147 |
148 | this.afterListElem = document.createElement(this.itemTagName);
149 | //This inserts after the templateElem. see http://stackoverflow.com/a/4793630/373655 for details
150 | this.templateElem.parentElement.insertBefore(this.afterListElem, this.templateElem.nextSibling);
151 |
152 | if (this.itemTagName.toLowerCase() === 'li') {
153 | this.beforeListElem.style.listStyleType = 'none';
154 | this.afterListElem.style.listStyleType = 'none';
155 | }
156 |
157 | this.firstUpdate = false;
158 | }
159 |
160 | private limitToRange(num, min, max) {
161 | return Math.max(
162 | Math.min(num, max),
163 | min
164 | );
165 | }
166 |
167 | }
--------------------------------------------------------------------------------
/src/lazyFor.module.ts:
--------------------------------------------------------------------------------
1 | import {NgModule} from '@angular/core';
2 | import {LazyForDirective} from './lazyFor.directive';
3 |
4 | @NgModule({
5 | declarations: [LazyForDirective],
6 | exports: [LazyForDirective]
7 | })
8 | export class LazyForModule {}
9 |
10 | export {LazyForDirective};
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "declaration": true,
4 | "module": "es2015",
5 | "target": "es5",
6 | "baseUrl": ".",
7 | "stripInternal": true,
8 | "experimentalDecorators": true,
9 | "moduleResolution": "node",
10 | "outDir": "./dist",
11 | "rootDir": "./src",
12 | "lib": ["es2015", "dom"],
13 | "skipLibCheck": true
14 | },
15 | "angularCompilerOptions": {
16 | "strictMetadataEmit": true,
17 | "skipTemplateCodegen": true
18 | }
19 | }
--------------------------------------------------------------------------------