Using Angular component in Non-Angular App
Tags: webdev, angular, javascript
Published: 2020-10-14 16:25:58

We all are mostly aware of the component-based approach and we create components in certain technologies that work within that technology environment. Like angular component works only in angular and Component created with Vue work only in Vue. 
> But what if I want to use a component I have created with angular on other platforms?


Let's start with What is web components and then do this magic with angular.
### Web Components
> Web components are a set of web platform APIs that allow you to create new custom, reusable, encapsulated HTML tags to use in web pages and web apps. Custom components and widgets build on the Web Component standards, will work across modern browsers, and can be used with any JavaScript library or framework that works with HTML.

```
<script type="module" src="./js/my-element.js"></script>
...
<my-element></my-element>
```

Using a custom element is pretty simple just like above code and you also can find how to create in javascript in [this article](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements)

This article is about creating such a web component using angular so that we can later use that element anywhere by just importing a single file so let's create one.

* Step-1 Create an angular project
> ng new web-components

* Step-2 Add element library
> ng add @angular/elements

* Step-3 Create web component inside the created directory
> ng generate component my-element

* Step-4 Write code in component
> I will create a simple counter component having two buttons for increment and decrement of the counter.

* Step-5 Open app.module.ts file and do following
Import following 
```
import { Injector } from '@angular/core';
import {createCustomElement} from '@angular/elements';
```
Remove the declaration of AppComponent, also remove it from bootstrap.
Remove the app.component.ts and related HTML, CSS and spec.ts file and it's import

- Add your component as an entry component inside @NgModule({})
```
entryComponents: [MyElementComponent]
```

- inject Injector in AppModule class and define a custom element

```
export class AppModule { 
  constructor(private injector: Injector) {}
  ngDoBootstrap() {
    const el = createCustomElement(MyElementComponent, { injector: this.injector });
    customElements.define('my-element', el);
  }
```

* Step-6 Write some code in your component...
* Step-7 Build the project
>ng build --prod --output-hashing none

* Step-8 Bundle the files generated in dist
Multiple files get generated in dist folder including main.js, pollyfill.js runtime.js and scripts.js. In newer versions, two types of files get generated (with es2015 and es5).
To concat files into a single file, 
first, install required dependency for concatenation
>npm install fs-extra concat

create a js file in the main folder and include the following code. I am naming it as bundle.js
```
const fs = require('fs-extra');
const concat = require('concat');
(async function build() {
    const files = [
        './dist/web-components/runtime-es5.js',
        './dist/web-components/polyfills-es5.js',
        './dist/web-components/scripts-es5.js',
        './dist/web-components/main-es5.js',
    ]
    await fs.ensureDir('elements')
    await concat(files, 'elements/my-element.js');
    await fs.copyFile('./dist/web-components/styles.css', 'elements/styles.css')    
})()
```

* Step-9 Run the following code to concat all files
> node bundle.js

New folder named elements will be created and you can now use that element by importing the generated file and rendering the element that you have mentioned while creating custom element in app.module.ts
```
<script src="my-element.js" ></script>
<h4>Element below is created in angular</h4>
<my-element></my-element>
```

* Step-10 Now run that HTML file in the browser and you will see that the component created in angular now working on a simple HTML page
Here is the codepen demo
{% codepen https://codepen.io/Mau1ik/pen/dyXGYYb default-tab=html,result %}

Here is the angular code 
{% github Maulikdes/web-components no-readme %}