@dotglitch/ngx-lazy-loader
Version:
A hackable lazy loader for Angular components
272 lines (229 loc) • 9.52 kB
Markdown
<a href="https://dotglitch.dev">
<h1 align="center">ngx-lazy-loader</h1>
</a>
<p align="center">
ngx-lazy-loader makes Lazy-loading Angular components a breeze. Now with Input bindings!
</p>
[](https://www.npmjs.com/package/@dotglitch/ngx-lazy-loader)
[](https://www.npmjs.com/package/@dotglitch/ngx-lazy-loader)
[](https://npmjs.org/@dotglitch/ngx-lazy-loader)
[](https://github.com/knackstedt/ngx-lazy-loader)
Quickstart
=====
## Install
```bash
$ npm install /ngx-lazy-loader
```
### Import with App Module
```typescript
import { NgModule } from '/core';
import { NgxLazyLoaderModule } from '/ngx-lazy-loader';
import { ProgressDistractorComponent } from './/progress-distractor/progress-distractor.component';
import { NotFoundComponent } from './/not-found/not-found.component';
import { ErrorComponent } from './/error/error.component';
import { Pages } from 'src/app/page.registry';
import { Dialogs } from 'src/app/dialog.registry';
import { Charts } from 'src/app/chart.registry';
({
declarations: [
AppComponent,
],
imports: [
...
NgxLazyLoaderModule.forRoot({
entries: [
...Pages,
...Dialogs,
...Charts
],
loaderDistractorComponent: ProgressDistractorComponent,
errorComponent: ErrorComponent,
notFoundComponent: NotFoundComponent
})
]
bootstrap: [AppComponent]
})
export class AppModule {
}
```
<!-- ### Import with App Component
```typescript
import { Component } from '/core';
import { NgxLazyLoaderModule } from '/ngx-lazy-loader';
import { RegisteredComponents } from 'src/app/component.registry';
({
...
imports: [
...
NgxLazyLoaderModule.forRoot({
entries: RegisteredComponents
})
,
standalone: true
})
export class AppComponent { }
```
component.registry.ts:
```ts
import { ComponentRegistration } from '/ngx-lazy-loader';
export const RegisteredComponents: ComponentRegistration[] = [
// Landing page -- neat.
{ id: 'Landing', load: () => import('src/app/pages/general/landing/landing.component'), icon: "home", order: 0 },
// About page
{ id: 'About', load: () => import('src/app/pages/general/about/about.component'), icon: "info", order: 10000 },
// Terms of use is a dialog
{ id: 'TermsOfUse', load: () => import('src/app/pages/general/termsofuse/termsofuse.component'), hidden: true },
]
```
> Notice that this has additional properties `icon`, `order` and `hidden`. These are used
> by the client application to render menus and are ignored by ngx-lazy-loader.
-->
### Loading a Component
```html
<ngx-lazy-loader
component="TestChild"
group="MyNonDefaultGroup"
[inputs]="{
prop1: value1,
prop2: value2
}"
[outputs]="{
buttonClicked: onChildButtonClicked.bind(this)
}"
/>
```
> As of release 0.0.17, outputs must be bound with .bind(this). We're working on improvements, but this is the most stable fix so far.
<!--
Examples
=====
[](https://stackblitz.com/github/avajs/ava/tree/main/examples/typescript-basic?file=source%2Ftest.ts&terminal=test&view=editor)
-->
Configuration
=====
```ts
NgxLazyLoaderModule.forRoot({
/**
* A list of lazy-loadable component registrations that we will
* initialize with. This list can be added to during runtime.
* Adding a component _after_ loading it via the lazy loader
* will not auto-resolve the component off of the notFoundComponent
*/
entries: RegisteredComponents,
/**
* A component to show when the loader can't resolve a provided ID
*/
notFoundComponent,
/**
* WIP: A component to show when something functionally fails when
* bootstrapping a lazy-loadable component.
* > usually happens in the constructor
*/
errorComponent,
/**
* A component to show as a progress spinner / distractor
*/
loaderDistractorComponent,
/**
* What strategy should be used to resolve components
* @default ComponentResolveStrategy.FuzzyIdClassName
*/
componentResolveStrategy: ComponentResolveStrategy,
/**
* When `componentResolveStrategy` is set to `Custom`,
* the method that identifies which component to resolve to.
*/
customResolver: (registry: (CompiledComponent | CompiledModule)[]) => Object
})
```
### Component Grouping
If you use a lot of components all over the place, you may need to group lazy-loadable
components in order to organize them and ensure that you don't encounter conflicts.
All you need to do when registering the component is add the group property:
component.registry.ts:
```ts
import { ComponentRegistration } from '/ngx-lazy-loader';
export const RegisteredComponents: ComponentRegistration[] = [
// Components are added into the "default" group unless otherwise specified.
{ id: 'Landing', load: () => import('src/app/pages/general/landing/landing.component')},
{ id: 'About', load: () => import('src/app/pages/general/about/about.component')},
{ id: 'TermsOfUse', group: "dialog", load: () => import('src/app/pages/general/termsofuse/termsofuse.component') },
{ id: 'PrivacyPolicy', group: "dialog", load: () => import('src/app/pages/general/privacypolicy/privacypolicy.component') },
{ id: 'barchart', group: "chart", load: () => import('src/app//barchart/barchart.component')},
{ id: 'piechart', group: "chart", load: () => import('src/app//piechart/piechart.component')},
{ id: 'areachart', group: "chart", load: () => import('src/app//areachart/areachart.component')},
{ id: 'mapchart', group: "chart", load: () => import('src/app//mapchart/mapchart.component')},
{ id: 'histogram', group: "chart", load: () => import('src/app//histogram/histogram.component')},
// You can overlap IDs as long as they have different groups
{ id: 'barchart', group: "dashboardtile", load: () => import('src/app/pages/dashboard//barchart/barchart.component')},
{ id: 'piechart', group: "dashboardtile", load: () => import('src/app/pages/dashboard//piechart/piechart.component')},
{ id: 'areachart', group: "dashboardtile", load: () => import('src/app/pages/dashboard//areachart/areachart.component')},
{ id: 'mapchart', group: "dashboardtile", load: () => import('src/app/pages/dashboard//mapchart/mapchart.component')},
{ id: 'histogram', group: "dashboardtile", load: () => import('src/app/pages/dashboard//histogram/histogram.component')},
]
```
Then, you just need to add the group when you reference the component:
```html
<ngx-lazy-loader
component="TestChild"
[inputs]="{
prop1: value1,
prop2: value2,
prop5: 'asd',
complex: complicated,
myExternalKey: 'balloon',
...
}"
[outputs]="{
prop3: onOutputFire,
buttonClicked: onChildButtonClicked,
...
}"
/>
```
### Using ID Matchers
```ts
const registry: ComponentRegistration[] = [
{
group: "editor",
matcher: [
"fruit",
"vegetables",
"legumes"
],
height: "750px",
width: "1450px",
load: () => import('src/app/pages/food-editor.component')
},
// This catches any value that doesn't exist on the previous matcher in the same group.
// Order of these entries matters.
{
group: "editor",
matcher: /.*/,
height: "700px",
width: "500px",
load: () => import('src/app/pages/generic-editor.component')
},
...
{
group: "dialogs",
// Custom matchers can be provided, and will check against the original input
matcher: (value: string) => value.contains("-dialog") && !value.contains("navigation"),
height: "750px",
width: "1450px",
load: () => import('src/app/pages/@dialogs/confirmation.component')
},
// If using matchers and no match can be made, the standard NotFound component/template is loaded
]
```
> This example contains additional properties on the registrations. When these are present, getting the matched component by running `this.lazyLoader.resolveRegistrationEntry(name, opts.group || "default")` from a DI injected instance of `private lazyLoader: NgxLazyLoaderService` will return the original entry. This can be used to additionally change parts of the UI as necessary.
Debugging
=====
### My Component doesn't load
- Look for formatted console logs.
### Component could not be resolved
- Make sure the component is registered and the registry is imported in your app.module
- Make sure the registration id is valid
- Make sure the registration group is the same as in the HTML attribute `<ngx-lazy-loader group="group1"/>`
- Check the registration matchers
- Check the specified component selector
> Matchers slugify the strings that they check