1
votes

I'm trying to export angular custom elements defined in a library L - through the constructor of the AppModule of the library L(customElements.define('my-custom-element', myComponent)).

On importing the library L, my angular application throws exception when using the element,

Uncaught Error: Template parse errors:
'my-custom-element' is not a known element.

Here is my public-api.ts file: https://github.com/sanjay51/IxAngularFramework/blob/master/projects/ix-angular-elements/src/public-api.ts

I couldn't find if it's even possible to export a custom element from a library. Any guidance in this regard will be appreciated.

Thanks.

Update:

Here is how I'm consuming the same, and how I declare my custom elements: https://github.com/sanjay51/IxAngularFramework/blob/master/src/app/app.module.ts

The problem that occurs this way is, my custom element is rendered twice, once as a component, and the second as a custom element.

Here is a snapshot: https://pasteboard.co/IkQtuJp.png

2
Import the library first then call that in constructor. - Chandan Y S
Hi Chandan, I've added the code for more context. Thanks! - Sanjay Verma
Just try declaring your classes in declaration section in app.module.ts. - Chandan Y S
Thanks Chandan. It still doesn't work, complains "IxFormComponent is part of the declarations of 2 modules", and I cannot remove it from the library (which is supposed to export the same). - Sanjay Verma

2 Answers

1
votes

You use the same tag name for the selector (ix-note and ix-form) of the Angular component and the custom element tag.
Therefore it gets created twice, because you use it inside an Angular application. Once Angular creates it (as an Angular component) and once the Browser (as a custom element / Angular Element).

This could be solved in several ways:
Either remove the selector from the Angular component, if it isn't used as Angular component anywhere else.
Or create a different tag for the custom element (e.g. ix-note-element) and use it in your HTML.

For both approaches you will have to add the following to your app module:

  schemas: [
    CUSTOM_ELEMENTS_SCHEMA
  ],

This tells Angular to keep calm if it detects tags like ix-note-element that it doesn't know.


Edit:

I digged a little bit deeper and now it's working: enter image description here

  1. Make sure to go with the second approach mentioned above. Use xy-element as the tag for the Angular Elements and add the CUSTOM_ELEMENTS_SCHEMA to the app.module.ts
  2. From app.module.ts, remove the constructor and the following code:
  entryComponents: [
    IxFormComponent,
    NoteComponent
  ]

(it only belongs to the ix-angular-elements.module.ts)
3. In ix-angular-elements.module.ts add the following constructor code:

  constructor(injector: Injector) {
    const formElement = createCustomElement(IxFormComponent, {injector: injector});
    customElements.define('ix-form-element', formElement);

    const noteElement = createCustomElement(NoteComponent, {injector: injector});
    customElements.define('ix-note-element', noteElement);
  }

This is only to register your custom elements in the Browser CE Registry. The library should be self contained so leave the code here. (This also prevents import issues)
4. Run npm install tslib (this was missing)
5. Add "@angular/forms": "^7.2.15" as peer dependencies to your library (projects/ix-angular-elements/package.json) (this was missing too)
6. (not sure if this rly was a problem) In ix-angular-elements.module.ts reimport all Angular packages with relative paths (you don't need to specify the path as a whole)
7. Use the library like this:

<ix-note title="Note" text="This is an Angular Component"></ix-note>
<ix-note-element title="Note" text="This is an Angular Element"></ix-note-element>
-1
votes

You need to import the component into your libraries module and the add it to the declarations and exports section of the module.

Then you need to add that module to the public-api.ts file in the library.

export { YourLibModule } from './lib/your-lib-module';

Then in the consuming app you need to import the YourLibModule.

Here is a public-api file from one of my libs.

https://github.com/adriandavidbrand/ngx-ez/blob/master/projects/ngx-ez/src/public-api.ts