Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Angular Elements With CodeMix

DZone's Guide to

Angular Elements With CodeMix

In this post, we check out one of the components that comes with the new version of Angular, and how you can use it in a web application.

· Web Dev Zone ·
Free Resource

Bugsnag monitors application stability, so you can make data-driven decisions on whether you should be building new features, or fixing bugs. Learn more.

Angular has been one of the best front-end JavaScript frameworks for some time now, and one of the many reasons is their continued effort to bring to new and improved ways to get the job done. One such effort is Angular Elements, which was introduced in Angular v6. In a nutshell, they convert components to HTML elements (+ JavaScript), allowing you to use your components in other apps, different frameworks (like React), or even in a simple HTML + JavaScript setup!

This is implemented using the new Custom Elements API supported by most modern browsers, and the process of converting a component to a custom element ensures all required Angular infrastructure (data binding, change detection, etc.) is available to the browser.

During the course of the article, we will be creating a panel that can display the title and content of a message, and a button to show or hide the message content. We'll then go ahead and use this panel in a simple HTML page.

Requirements

You are expected to have a basic knowledge of Angular and component development.

You are also required to have the following installed on your computer:

We are going to take advantage of CodeMix to show you how it will configure the working environment for Angular development.

Creating an Angular Project in CodeMix

We'll be using the latest version of all the tech libraries and stacks, as of the time of writing. To create a new Angular Project, navigate to File > New > Project > CodeMix > Angular Project. Then click Next and enter your project name on the following screen. Finally, click Finish to continue with Angular project creation.

Image title

Creating a new Angular project in CodeMix

We will now open a terminal for a project using the command palette by pressing Ctrl/Cmd + Shift + P; then type terminal: create a new integrated terminal and select your project from the drop-down. The terminal will automatically be opened in the project folder.

Image title

Opening a terminal in CodeMix

  • Once you are inside the terminal, execute: npm install
  • Finally, run the Angular app by executing ng serve
  • To see the Angular app running live, open your browser to http://localhost:4200

Now we need to pull in the Angular element modules and the poly-fills for browser compatibility since they are not fully supported in some browsers, especially (you guessed it!) Microsoft Edge and Internet Explorer.

First the Angular Elements module:
npm install @angular/elements

Then the poly-fill we will be using in the article:
npm install @webcomponents/custom-elements

Developing the Component

First, we create our component, which we will name hideaway-message – it is recommended to have yours include the domain name and a hyphen in your custom element so that it won’t clash with preexisting elements. For example, if your project name is flyOne, the element you create could be named fly-one-button. We will create ours using the command below:

ng g component hideaway-message

Image title

Creating components in CodeMix terminal

We can now begin to develop our regular Angular component. First, we define our template with the ./src/app/hideaway-message/hideaway-message.component.html file (although this could be done in the component main file).

<div class="panel panel-default">
        <div class="panel-heading">
                {{title}}
                <button (click)="hideContent($event)" style="float: right"> 
                  {{ btnText }} 
                </button>
        </div>
        <div class="panel-body" *ngIf="!hidden">
                {{content}}
        </div>
</div>

We also add our styling in our ./hideaway-message.component.css within the same folder as the template file:

.panel {
    margin: 10px;
    background-color: #fff;
    border: 1px solid transparent;
    border-radius: 4px;
    -webkit-box-shadow: 0 1px 1px rgba(0,0,0,.05);
    box-shadow: 0 1px 1px rgba(0,0,0,.05);
}
.panel-default {
    border-color: #ddd;
}
.panel-default>.panel-heading {
    color: #333;
    background-color: #f5f5f5;
    border-color: #ddd;
}
.panel-heading {
    padding: 10px 15px;
    border-bottom: 1px solid transparent;
    border-top-left-radius: 3px;
    border-top-right-radius: 3px;
}
.panel-body {
    padding: 15px;
}

We can now define our component in the hideaway-message.component.ts file like this:

import { Component, Input, ViewEncapsulation } from '@angular/core';
@Component({
  selector: 'hideaway-message',
  templateUrl: './hideaway-message.component.html',
  styleUrls: ['./hideaway-message.component.css',],
  encapsulation: ViewEncapsulation.Native
})
export class HideawayMessageComponent {
  constructor() { }
  hidden = false;
  btnText = 'Hide'
  hideContent(e) {
          e.preventDefault();
          this.hidden = !this.hidden;
          this.btnText = this.btnText == 'Hide' ? 'Show' : 'Hide';
  }
  @Input() content;
  @Input() title;
}

ViewEncapsulation helps compile the CSS down to JavaScript (i.e., using Shadow DOM), so the component can be used without having to worry about the CSS referencing properly. We can now check to see if our component is working by putting it within the app-root tag in the index.html file:

<body>
  <app-root>
    <hideaway-message title="Lorem ipsum dolor sit amet" 
          content="Lorem ipsum dolor sit amet, iusto appellantur vix te, nam affert feugait menandri eu. Magna simul ad est. Nostrum neglegentur ius at, at pertinax repudiare vel. Vim an adolescens quaerendum.">
    </hideaway-message>
  </app-root>
</body>

We now start our application so it can be in a browser (on the default Angular port http://localhost:4200/) using the command below in the command line:

ng serve

Now that our component is fully functional, the next step is to convert it into an Angular element. We do this by editing the app.module.ts file to look like this:

import { BrowserModule } from '@angular/platform-browser';
import { NgModule, Injector } from '@angular/core';
import { createCustomElement } from '@angular/elements';
import { HideawayMessageComponent } from './hideaway-message/hideaway-message.component';
import { AppComponent } from './app.component';

@NgModule({
  declarations: [
    HideawayMessageComponent,
    AppComponent
  ],
  imports: [
    BrowserModule
  ],
  entryComponents: [
    HideawayMessageComponent
  ]
})
export class AppModule {
        constructor(private injector: Injector){
        }
        ngDoBootstrap(){
                const element = createCustomElement(
                        HideawayMessageComponent,
                        { injector: this.injector }
                        );
                customElements.define('hideaway-message', element)
        }
}

In the code above, we have stopped Angular from automatically bootstrapping the application. We accomplished that by removing the bootstrap property in the decorator parameter object and overwriting the ngDoBootstrap method in the AppModule class. We also add the component, HidawayMassageComponent to the entryComponents array, to instruct Angular to create the component, even though it is not part of a template.

Then within ngDoBootstrap method, the HidawayMassageComponent is parsed using the function createCustomElement from the Angular element module to prepare it to be added to CustomElementRegistry (this process includes making the component extend the HTMLElement abstract class). After the component has been transformed into an element, we then add it to the list of elements available to the DOM using customElement object which is available globally in JavaScript. Now we can use the element in an HTML file within our project. For example, the index.html file could be rewritten as below:

<body>
    <div style="width: 90%; margin: auto;">
          <hideaway-message 
            title="Lorem ipsum dolor sit amet" 
            content="Lorem ipsum dolor sit amet, iusto appellantur vix te.">
          </hideaway-message>
          <hideaway-message 
            title="Lorem ipsum dolor sit amet" 
            content="Lorem ipsum dolor sit amet, iusto appellantur vix te.">
          </hideaway-message>
          <hideaway-message 
            title="Lorem ipsum dolor sit amet" 
            content="Lorem ipsum dolor sit amet, iusto appellantur vix te.">         
          </hideaway-message>
          <hideaway-message 
            title="Lorem ipsum dolor sit amet" 
            content="Lorem ipsum dolor sit amet, iusto appellantur vix te.">
          </hideaway-message>
    </div>
</body>

Building the Custom Element

Now that we can use the element in an HTML document within our project, the next step is to try to make sure that we can use the element by referencing a file with the element declaration and dependencies. For this, we need to pull in a module called concat, using npm:

npm install concat --save-dev

Next, we create a build script in the root of the project folder and name it accordingly. In the build-script.js file, we add the path to the production build files and a path to the output file after concatenation, and pass it to the concat function like below:

const concat = require('concat');
const files = [
        './dist/AngularElements/runtime.js',
        './dist/AngularElements/polyfills.js',
        './dist/AngularElements/main.js'
    ];
const outputFile = './dist/final-bundle.js';
concat(files, outputFile);

This list of files is the product of the Angular build command, and these files are usually found in the dist directory in the project root directory - please replace AngularElements in the paths above with the name of your project. Please note that these paths are specific to Angular apps built with version 6.0 of the CLI or higher.

We need to add a script in the package.json file to firstly build our application in prod mode, without hashing the output file, and run our build-script. We add the code below to the scripts object:

"build-element": "ng build --prod --output-hashing=none && node build-script.js"


Image title

Code Formatting using CodeMix

Now we can run the command below to get our concatenated file:

npm run build-element

Using the Custom Element

The final-bundle.js file created by the above script can now be used anywhere. Copy this file to another location, and create a simple HTML file in the same folder with the following code:

<body>
        <div style="width: 90%; margin: auto;">
          <hideaway-message
            title="Lorem ipsum dolor sit amet"
            content="Lorem ipsum dolor sit amet, iusto appellantur vix te.">
          </hideaway-message>
          <hideaway-message 
            title="Lorem ipsum dolor sit amet" 
            content="Lorem ipsum dolor sit amet, iusto appellantur vix te.">
          </hideaway-message>
        </div>
        <script type="text/javascript" src="final-bundle.js"></script>
</body>

It should look like this in the browser:

Image title


Angular Element in an HTML file

Awesome, it works - we just used the Angular component we built in a simple HTML file!

Conclusion

Angular elements are here to help make the development of applications smoother and less restrictive. It will be very important in server-side rendering (SSR), and it also allows us to use our component, developed in Angular, in other non-Angular applications, such as those developed in Reac.js, Vue.js, etc.

Although it has its benefits, it comes with some significant drawbacks, which include the fact that the size of the script added to the HTML (about 233KB in this case) is quite big for just one element. Also, it is not fully supported by most browsers, as stated before, and there are compatibility issues with some of the prior Angular releases. Despite these drawbacks, Angular elements are still a handy tool – hopefully Angular 7 will address these issues.

Monitor application stability with Bugsnag to decide if your engineering team should be building new features on your roadmap or fixing bugs to stabilize your application.Try it free.

Topics:
web dev ,angular ,web application development ,angular 6 ,angular elements

Published at DZone with permission of

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}