Using Web Components in AngularJS
Tags: angular, webcomponents, clarity
Published: 2020-07-22 02:59:12

---
title: Using Web Components in AngularJS
published: true
date: 2020-07-13 05:00:00 UTC
tags: angularjs,webcomponents,clarity
canonical_url: https://coryrylan.com/blog/using-web-components-in-angular-js
---

AngularJS has been around for quite some time on the Web. Many legacy AngularJS apps need to be migrated or upgraded to the latest Angular or other UI frameworks like Vue or React. There are many challenges when upgrading or migrating an AngularJS application, as well as many different approaches. In this post, we will see how Web Components allow us to create a compatibility bridge between different Web technologies.

Web Components [(Custom Elements)](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements) are a Web standard for defining custom HTML tags. Web Components work similarly to other component models allowing data to be passed in via Properties/Attributes and notify of changes to the host application through Custom Events.

We won’t dig deep into how to build Web Components but instead focus on integrating them into AngularJS. To get an introduction to [Web Components, check out this post](https://coryrylan.com/blog/introduction-to-web-components).

## Setting Up

When using Web Components in AngularJS, your application must be on version 1.7.3 or higher. To start, we will set up a basic AngularJS app.

```html
<!doctype html>
<html>
<head></head>

<body>
  <app-root></app-root>
</body>
<script src="./index.js"></script>
</html>
```

```javascript
import angular from 'angular';

angular.module('app', []);
angular.element(document).ready(() => angular.bootstrap(document, ['app']));

angular.module('app').component('appRoot', {
  template: `
    hello world
  `,
  controller: function () { }
});
```

In our basic AngularJS app, we create a root app module as well as a single Angular component called `appRoot`. In this example, we will use a third party Web Component to demonstrate how Web Components integrate with AngularJS. Our Web Component for this example will come from the [Clarity Design System](https://clarity.design/storybook/core), which provides an extensive UI Web Components suite. Web Components can be installed like any other NPM package.

```bash
npm install --save @clr/core
```

Once the package is installed, we can start importing the components we would like to use. The import path or registration step may vary between libraries, so be sure to check the latest documentation.

```javascript
import angular from 'angular';
import '@clr/core/button/register';

angular.module('app', []);
angular.element(document).ready(() => angular.bootstrap(document, ['app']));

angular.module('app').component('appRoot', {
  template: `
    <cds-button>hello there</cds-button>
  `,
  controller: function () { }
});
```

Here we added a simple button Web Component from the Clarity Design System. If we look at our running app, we will see the following:

![Web Component Button from Clarity Design System in AngularJS](https://coryrylan.com/assets/images/posts/2020-07-14-using-web-components-in-angular-js/button-web-component.png)

## Properties and Attributes

Web Components can accept data in a few different ways. Web Components can receive projected content between its element tags and values passed via attributes and properties.

When passing data to a Web Component, its important to understand the differences between attributes and properties. Attributes can be set via HTML and are always string values.

```html
<cds-alert-group status="danger"></cds-alert-group>
```

However, if we wanted to pass an Object or Array to the component, it would not work as attributes are always strings in HTML. To set complex values, we have to set the property.

```javascript
const component = document.querySelector('my-custom-element');
component.someProperty = { greeting: 'hello there' };
```

For Angular, however, we don’t need to use `document.querySelector`. Instead, we can use the `ng-prop` directive. This directive allows us to set the JavaScript property on an element instead of using attributes. Let’s add an alert component to display a message and update its status via our Controller properties.

```javascript
import angular from 'angular';
import '@clr/core/alert/register';
import '@clr/core/button/register';

angular.module('app', []);
angular.element(document).ready(() => angular.bootstrap(document, ['app']));

angular.module('app').component('appRoot', {
  template: `
    <cds-button status="primary">hello there</cds-button>

    <cds-alert-group ng-prop-status="$ctrl.status">
      <cds-alert>
        General Kenobi. You are a bold one.
      </cds-alert>
    </cds-alert-group>
  `,
  controller: function () {
    this.status = 'danger';
  }
});
```

In the example above, we can see we use the `status` attribute to set the button’s status but use `ng-prop` to bind the JavaScript property of our controller to the corresponding JavaScript `status` property on the alert component. Both are valid, but `ng-prop` will work with all value types.

## Custom Events

Web Components can be used like any other component and have event listeners. Let’s add a click event and show the alert message when the button is clicked.

```javascript
import angular from 'angular';
import '@clr/core/alert/register';
import '@clr/core/button/register';
import './style.css';

angular.module('app', []);
angular.element(document).ready(() => angular.bootstrap(document, ['app']));

angular.module('app').component('appRoot', {
  template: `
    <cds-button ng-click="$ctrl.showAlert = true">hello there</cds-button>
    
    <cds-alert-group ng-if="$ctrl.showAlert" ng-prop-status="$ctrl.status">
      <cds-alert>
        General Kenobi. You are a bold one.
      </cds-alert>
    </cds-alert-group>
  `,
  controller: function () {
    this.status = 'danger';
    this.showAlert = false;
  }
});
```

On our Angular controller, we use a boolean to show the alert when the button is clicked.

![Web Components from Clarity Design System in AngularJS](https://coryrylan.com/assets/images/posts/2020-07-14-using-web-components-in-angular-js/web-components-in-angularjs.png)

The Alert Web Component has a closable feature and can emit an event when the user has clicked the close button. We can use the Custom Event to hide the alert in our Angular template. To listen to Custom Events, we use the `ng-on` directive.

```javascript
import angular from 'angular';
import '@clr/core/alert/register';
import '@clr/core/button/register';
import './style.css';

angular.module('app', []);
angular.element(document).ready(() => angular.bootstrap(document, ['app']));

angular.module('app').component('appRoot', {
  template: `
    <cds-button ng-click="$ctrl.showAlert = true">hello there</cds-button>

    <cds-alert-group ng-if="$ctrl.showAlert" ng-prop-status="$ctrl.status">
      <cds-alert ng-on-close_change="$ctrl.showAlert = false" closable>
        General Kenobi. You are a bold one.
      </cds-alert>
    </cds-alert-group>
  `,
  controller: function () {
    this.status = 'danger';
    this.showAlert = false;
  }
});
```

With the `ng-on` directive, we add the event’s name to the end of the directive and an Angular expression on the right-hand assignment. Note since our template is HTML, we lose case-sensitivity; however, Custom Events are case sensitive. Because of this, upper case letters need to have a `_` prefix.

The alert component emits a `closeChange` custom event so our template would be `ng-on-close_change=""`. Now we can listen for the close event on our alert.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/dkdtswm0unnktfovksbz.png)

With Web Components, we can pass data, listen for events, and share logic between different UI setups. Web Components are a great way to encapsulate UI into a standard component model. To learn more about Web Components, check out a few of these tutorials. The working demo can be found below!

- [Demo AngularJS + Web Components](https://stackblitz.com/edit/typescript-bzqhnr)
- [Introduction to Web Components](https://coryrylan.com/blog/introduction-to-web-components)
- [Using Web Components in Angular](https://coryrylan.com/blog/using-web-components-in-angular)
- [Using Web Components in Vue](https://coryrylan.com/blog/using-web-components-in-vue)
- [Using Web Components in React](https://coryrylan.com/blog/using-web-components-in-react)