javascriptangulartypescriptweb-component

Importing vs Rendering of custom Web Components in Angular


We are building a native JS web component library (Foo Web Components, or FWC), and we are trying to use it in an Angular application (for now, without a wrapper).

Our relevant files now look as follow:

app.component.ts:

import { Component, CUSTOM_ELEMENTS_SCHEMA, ElementRef, ViewChild } from '@angular/core';

import { FWCInput, FWCDatepicker } from '@foo/foo-web-components';

@Component({
  selector: 'app-root',
  standalone: true,
  templateUrl: './app.component.html',
  styleUrl: './app.component.css',
  schemas: [CUSTOM_ELEMENTS_SCHEMA]
})
export class AppComponent {
  public today: Date = new Date();
  //@ts-ignore
  @ViewChild("datepicker") datepicker: ElementRef<FWCDatepicker>;
  //@ts-ignore
  @ViewChild("input") input: ElementRef<FWCInput>;

  constructor() { }

  ngAfterViewInit(): void {
    console.log(this.datepicker);
    console.log(this.input);
  }
}

app.component.html:

Datepicker: <fwc-datepicker #datepicker [date]="today" label="Datepicker"></fwc-datepicker>
Input: <fwc-input #input placeholder="placeholder" value="From Template" label="Input"></fwc-input>

With this configuration, the page looks like this: not-working No errors in the console or build process, but the components aren't in the DOM or rendered.

However, if we add a single line in the constructor of the app.component.ts as so:

  constructor() {
    var foo = new FWCInput();
  }

Suddenly the components appear: working

I'm assuming it's got to do with something related to when Angular actually loads an import... If it's "not actually used" (as perceived by the framework) it won't load it. However, when we import just ONE of the members from the library (in this case, the FWCInput), the whole library gets pulled-in and everything works (including the FWCDatepicker which wasn't referenced in a new variable).

Why is this, and how would we go about as library designers to allow users to just "use" our components without instantiating disposable variables?

EDIT: Removed the fwc.module.ts file since it wasn't needed (came from previous tests...).


Solution

  • I think you just need to add the source code to the root of the application, then the component will begin rendering.

    We cannot add the components to providers, since they are just classes, providers array accepts only classes that have the decorator @Injectable().

    Only if you import the source code will you be able to use the component is my understanding.

    import '@foo/foo-web-components'; // <- changed here
    import { FWCInput, FWCDatepicker } from '@foo/foo-web-components';
    
    @Component({
      selector: 'app-root',
      standalone: true,
      templateUrl: './app.component.html',
      styleUrl: './app.component.css',
      schemas: [CUSTOM_ELEMENTS_SCHEMA]
    })
    export class AppComponent {
      public today: Date = new Date();
      //@ts-ignore
      @ViewChild("datepicker") datepicker: ElementRef<FWCDatepicker>;
      //@ts-ignore
      @ViewChild("input") input: ElementRef<FWCInput>;
    
      constructor() { }
    
      ngAfterViewInit(): void {
        console.log(this.datepicker);
        console.log(this.input);
      }
    }