Lazy Loading Angular Third Party

You are lazy loading everything in your Angular application, and you say … hmmmm, wait, what if I want to lazy load everything, like EVERYTHING !!, you lazy loaded your modules, components, but you’re thinking of lazy loading Angular third party dependencies, well, that’s good, but, even great, but how to do that?

lazy cat

First Steps

You are interested in lazy loading third party libraries or dependencies like ag-grid. In that case, you can still leverage lazy loading, but it might be a bit different from lazy loading your own modules or components, the key is to use dynamic imports for the third party libraries.

An example of how you can lazy load ag-grid in an Angular application:

  1. Install ag-grid:
    First, make sure you have ag-grid installed in your project.
   npm install --save ag-grid-angular ag-grid-community
  1. Lazy Load ag-Grid Module:
    In your code, use dynamic import to load the ag-grid module when needed. You can create a service to encapsulate this logic.
   // ag-grid-loader.service.ts
   import { Injectable } from '@angular/core';

   @Injectable({
     providedIn: 'root',
   })
   export class AgGridLoaderService {
     private agGridModule: any;

     async loadAgGridModule(): Promise<any> {
       if (!this.agGridModule) {
         this.agGridModule = await import('ag-grid-angular');
       }
       return this.agGridModule;
     }
   }
  1. Usage in Component:
    In your component, use the service to lazy load the ag-grid module when needed.
   // your.component.ts
   import { Component, OnInit } from '@angular/core';
   import { AgGridLoaderService } from './ag-grid-loader.service';

   @Component({
     selector: 'app-your-component',
     templateUrl: './your.component.html',
     styleUrls: ['./your.component.css'],
   })
   export class YourComponent implements OnInit {
     constructor(private agGridLoaderService: AgGridLoaderService) {}

     async ngOnInit(): Promise<void> {
       const agGrid = await this.agGridLoaderService.loadAgGridModule();
       // Now you can use ag-Grid components and features
     }
   }

This way, the ag-grid module will only be loaded when the component is initialized, providing a form of lazy loading for third party dependencies. Keep in mind that the actual implementation might vary based on the specific library and how it exposes its modules. Always refer to the documentation of the library you are trying to lazy load for the correct way to import and use it dynamically.

Using it in your html template – Final Lazy Loading

When you are working with dynamic imports and lazy-loaded modules, it’s important to understand that the Angular template parser is not aware of components that are loaded dynamically. As a result, using dynamic components in the template requires a slightly different approach.

Here’s an example of how you can use the dynamic-loaded ag-grid component in your Angular template:

Assuming you have a component that uses ag-grid, you’ll need to load the component dynamically and create it programmatically.

  1. Modify Your Service to Include Component:
   // ag-grid-loader.service.ts
   import { Injectable, ComponentFactoryResolver, ApplicationRef, Injector } from '@angular/core';

   @Injectable({
     providedIn: 'root',
   })
   export class AgGridLoaderService {
     private agGridModule: any;

     constructor(
       private componentFactoryResolver: ComponentFactoryResolver,
       private appRef: ApplicationRef,
       private injector: Injector
     ) {}

     async loadAgGridModule(): Promise<any> {
       if (!this.agGridModule) {
         this.agGridModule = await import('ag-grid-angular');
       }
       return this.agGridModule;
     }

     createAgGridComponent(): any {
       // Assuming AgGridComponent is the component provided by ag-grid
       const componentFactory = this.componentFactoryResolver.resolveComponentFactory(
         this.agGridModule.AgGridComponent
       );
       const componentRef = componentFactory.create(this.injector);
       this.appRef.attachView(componentRef.hostView);
       return componentRef;
     }
   }
  1. Use the Component in Your Angular Component:
   // your.component.ts
   import { Component, ElementRef, OnInit, ViewChild } from '@angular/core';
   import { AgGridLoaderService } from './ag-grid-loader.service';

   @Component({
     selector: 'app-your-component',
     template: '<div #agGridContainer></div>',
   })
   export class YourComponent implements OnInit {
     @ViewChild('agGridContainer', { read: ElementRef, static: true }) agGridContainer!: ElementRef;

     private agGridComponentRef: any;

     constructor(private agGridLoaderService: AgGridLoaderService) {}

     async ngOnInit(): Promise<void> {
       const agGridModule = await this.agGridLoaderService.loadAgGridModule();
       this.agGridComponentRef = this.agGridLoaderService.createAgGridComponent();

       // Append the component to the container in the template
       this.agGridContainer.nativeElement.appendChild(
         (this.agGridComponentRef.hostView as any).rootNodes[0]
       );
     }
   }
  1. Remember to Destroy the Component: When your component is destroyed, make sure to clean up and destroy the dynamically created ag-grid component to avoid memory leaks.
   ngOnDestroy(): void {
     if (this.agGridComponentRef) {
       this.agGridComponentRef.destroy();
     }
   }

This approach allows you to use a dynamically loaded ag-grid component in your template. Keep in mind that handling the dynamic component’s lifecycle and cleanup is important to prevent memory leaks.

Don’t forget to check the other Angular Articles ! here’s a lazy potato !

lazy potato