Angular Extensions Elements

repository·master·Indexed 43 days ago

https://github.com/angular-extensions/elements

A library for lazy-loading Angular Elements and web components within Angular applications. It provides the *axLazyElement and *axLazyElementDynamic structural directives, along with the LazyElementsLoaderService for managing loading registries, preloading, and lifecycle hooks. Version 22.0.0 supports various Angular versions, including full Ivy support for 9.x.

Tokens
5.8K
Snippets
21
Records
28
Agent score
55%

What's inside Angular Extensions Elements

  1. Install and set up @angular-extensions/elements

    master

    To use @angular-extensions/elements for lazy-loading Angular Elements or web components in your Angular application, follow these steps:

    1. Install the package via npm: npm i @angular-extensions/elements
    2. Import LazyElementDirective from @angular-extensions/elements.
    3. Add LazyElementDirective to the imports array of your Angular component.
    4. Add CUSTOM_ELEMENTS_SCHEMA to the schemas array of your @Component decorator to allow the use of non-Angular custom elements.
    5. Apply the *axLazyElement structural directive to the HTML element you want to lazy-load, passing the URL of the element bundle as the argument.
    npm i @angular-extensions/elements
  2. Configure lifecycle hooks for element loading

    master

    You can define beforeLoad and afterLoad hooks at three different levels of granularity. The service resolves which hook to use in the following order of precedence:

    1. Method Level: Passed directly to loadElement() via hooksConfig.
    2. Config Level: Defined within a specific ElementConfig object passed to addConfigs().
    3. Global Level: Defined in the LAZY_ELEMENT_ROOT_OPTIONS provided to the service.

    Hook Signatures:

    • beforeLoad: A function that returns a Promise<void>. The script loading process will wait for this promise to resolve before appending the script to the document.
    • afterLoad: A function that returns a Promise<void>. This is executed after the script has loaded.
  3. Use Hooks to intercept element loading

    master

    The HooksConfig allows you to execute logic at specific points in the element lifecycle.

    • beforeLoad: A function called before the element starts loading. It can be synchronous or return a Promise<void>.
    • afterLoad: A function called after the element has successfully loaded.

    Both hooks receive the tag (the HTML tag name) as an argument.

    const hooks: HooksConfig = {
      beforeLoad: async (tag) => {
        await someAsyncSetup();
        console.log('Starting load for:', tag);
      },
      afterLoad: (tag) => {
        console.log('Finished loading:', tag);
      }
    };
  4. Configure loading and error states for *axLazyElementDynamic

    master

    When using *axLazyElementDynamic, you can customize the UI during the loading and error phases using either template references or component classes.

    Pass an <ng-template> reference to axLazyElementDynamicLoadingTemplate or axLazyElementDynamicErrorTemplate.

    Component-based

    If no template is provided, the directive will attempt to use a loadingComponent or errorComponent configured globally via the LazyElementsLoaderService options or specifically for that tag via ElementConfig.

  5. Use the *axLazyElement directive to lazy-load elements

    master

    The *axLazyElement directive allows you to lazy-load a web component or Angular Element by providing its bundle URL. Once loaded, the element supports standard Angular template bindings, such as property bindings [] and event bindings ().

    Ensure your component includes LazyElementDirective in its imports and CUSTOM_ELEMENTS_SCHEMA in its schemas.

    import { Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
    import { LazyElementDirective } from '@angular-extensions/elements';
    
    @Component({
      selector: 'your-org-feature',
      imports: [LazyElementDirective],
      schemas: [CUSTOM_ELEMENTS_SCHEMA],
      template: `
        <!-- will be lazy loaded and uses standard Angular template bindings -->
        <some-element
          *axLazyElement="elementUrl"
          [data="data"
          (dataChange="handleChange($event)"
        ></some-element>
      ',
    })
    export class MyOrgComponent {
      elementUrl = 'https://your-org.com/elements/some-element.js';
    
      data: SomeData;
    
      handleChange(change: Partial<SomeData>) {
        // ...
      }
    }
  6. Configure highlight.js with ngx-highlightjs

    master

    To use highlight.js within an Angular application via ngx-highlightjs, provide the HIGHLIGHT_OPTIONS token in your application configuration. You must define a coreLibraryLoader to load the core library and a languages object that maps language identifiers to dynamic import functions for their respective language modules.

    import { HIGHLIGHT_OPTIONS } from 'ngx-highlightjs';
    
    export const HIGHLIGHT_JS_PROVIDER = {
      provide: HIGHLIGHT_OPTIONS,
      useValue: {
        coreLibraryLoader: () => import('highlight.js/lib/core'),
        languages: {
          typescript: () => import('highlight.js/lib/languages/typescript'),
          xml: () => import('highlight.js/lib/languages/xml'),
        },
      },
    };
  7. Supported Angular versions

    master

    The library is designed to be used with corresponding major versions of Angular (e.g., @angular/core ^15.0.0 with @angular-extensions/elements ^15.0.0). Supported versions include:

    • 9.x: Full Ivy support (uses renderers; use caution with SSR).
    • 8.x: Partial Ivy support. Note that *axLazyElement works, but axLazyElementDynamic does NOT work with Ivy.
    • 7.x
    • 6.x: Install via npm i @angular-extensions/elements@^6.0.0.
  8. Troubleshoot LazyElementsModule.forRoot() multiple execution guard

    master

    If you receive a TypeError stating LazyElementsModule.forRoot() called twice. Lazy feature modules should use LazyElementsModule.forFeature() instead., it means you are attempting to initialize the root configuration in more than one place.

    Resolution:

    1. Ensure LazyElementsModule.forRoot() is only called in your main AppModule (or the entry point of your application).
    2. For any subsequent modules or lazy-loaded routes that require element configurations, replace forRoot() with forFeature().
  9. Configure Lazy Elements via LAZY_ELEMENT_CONFIGS

    master

    Use the LAZY_ELEMENT_CONFIGS injection token to provide an array of ElementConfig objects. This allows you to define the configuration for multiple web components/elements that the library will manage.

    import { LAZY_ELEMENT_CONFIGS } from '@angular-extensions/elements';
    
    // In your AppModule or component providers
    providers: [
      {
        provide: LAZY_ELEMENT_CONFIGS,
        useValue: [
          { /* your ElementConfig configuration */ }
        ]
      }
    ]
  10. Manage web component loading with LazyElementsLoaderService

    master

    The LazyElementsLoaderService is the core service responsible for orchestrating the lazy-loading of Angular Elements or other web components. It manages a registry of loading promises to prevent duplicate network requests and provides mechanisms for preloading, manual loading, and lifecycle hooks.

    Key capabilities:

    • Automatic Preloading: If preload is enabled in the global options or the specific ElementConfig, elements are loaded as soon as they are registered.
    • Manual Preloading: You can trigger the loading of specific elements or all registered elements using the preload() method.
    • Lifecycle Hooks: Supports beforeLoad and afterLoad hooks to execute logic before the script is appended to the DOM or after the script has finished loading.
    • Import Maps: Supports resolving URLs via SystemJS when the importMap flag is set.
    • Module Support: Can load scripts as ES modules by setting the isModule flag.
  11. Preload specific elements with preload()

    master

    The preload(tags?: string[]) method allows you to proactively load web component bundles.

    • If called without arguments, it attempts to preload all currently registered configurations.
    • If called with an array of strings, it only preloads the elements whose tag matches the provided list.
    // Preload all registered elements
    loaderService.preload();
    
    // Preload only specific tags
    loaderService.preload(['my-element', 'other-element']);
  12. Configure LazyElementsModule using forRoot()

    master

    To initialize the lazy-loading capabilities of Angular Elements in your application, use LazyElementsModule.forRoot() in your root module (usually AppModule). This method allows you to define global configurations for the elements you want to lazy-load and set root-level options.

    Use forRoot() to provide:

    • elementConfigs: An array of configurations for specific elements.
    • rootOptions: Global settings for the lazy-loading behavior.

    Note: forRoot() should only be called once in your application. If you attempt to call it multiple times in development mode, the library will throw a TypeError to prevent configuration conflicts.

    import { LazyElementsModule } from '@angular-extensions/elements';
    
    @NgModule({
      imports: [
        LazyElementsModule.forRoot({
          elementConfigs: [
            // your element configurations here
          ],
          rootOptions: {
            // your root options here
          }
        })
      ],
      // ...
    })
    export class AppModule { }