Socket
Socket
Sign inDemoInstall

@hapiness/custom-elements-loader

Package Overview
Dependencies
14
Maintainers
1
Versions
14
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

    @hapiness/custom-elements-loader

Factory to load Angular Custom Elements inside JavaScript's applications like React.js, Vue.js or just standalone


Version published
Maintainers
1
Created

Readme

Source
Hapiness
build dependencies devDependencies

CUSTOM-ELEMENTS-LOADER

This module exposes a factory to use ElementsLoaderService inside JavaScript's applications like React.js, Vue.js or just standalone.

DON'T USE THIS MODULE FOR ANGULAR APPLICATION

Installation

$ yarn add @hapiness/custom-elements-loader

or

$ npm install --save @hapiness/custom-elements-loader

All required dependencies will be automatically installed : @angular/animations, @angular/common, @angular/core, @angular/compiler, @angular/elements, @angular/platform-browser, @angular/platform-browser-dynamic, @hapiness/ng-elements-loader, core-js, document-register-element, rxjs and zone.js.

If your custom element module must have more dependencies, you must install them by yourself

Usage

Before to use ElementsLoader exposed by @hapiness/custom-elements-loader, you must create your own custom-elements modules.

To create a new library with Angular-CLI, follow this guide.

1) made-with-love custom element

- Component

This component will be the final custom-element interpreted in your browser.

projects/made-with-love/src/lib/made-with-love.component.ts:

import { Component, Input, OnInit, ViewEncapsulation } from '@angular/core';

@Component({
  selector: 'made-with-love',
  templateUrl: './made-with-love.component.html',
  encapsulation: ViewEncapsulation.Native
})
export class MadeWithLoveComponent implements OnInit {
  private _name: string;
  private _url: string;
  private _color: string;
  private _size: number;

  constructor() {
    this.size = 1;
    this.color = 'red';
  }

  ngOnInit() {
    if (!this._name || this._name.length === 0) {
      console.error(`Name attribute must be provided!`);
    }
  }
  
  get name(): string {
    return this._name;
  }
  
  @Input()
  set name(n: string) {
    this._name = n;
  }
  
  get url(): string {
    return this._url;
  }

  @Input()
  set url(u: string) {
    this._url = u;
  }
  
  get color(): string {
    return this._color;
  }

  @Input()
  set color(c: string) {
    this._color = c;
  }
  
  get size(): number {
    return this._size;
  }

  @Input()
  set size(s: number) {
    this._size = s;
  }
}

Note: Your component must have encapsulation equals to ViewEncapsulation.Native.

projects/made-with-love/src/lib/made-with-love.component.html:

<ng-template #noUrl>
  {{ name }}
</ng-template>
<span [style.font-size.em]="size">
  Made with <span [style.color]="color"></span> by
  <ng-container *ngIf="url && url.length > 0; else noUrl">
    <a [attr.href]="url" target="_blank">{{ name }}</a>
  </ng-container>
</span>
- Module

projects/made-with-love/src/lib/made-with-love.module.ts:

import { NgModule, Type } from '@angular/core';
import { CommonModule } from '@angular/common';
import { WithCustomElementComponent } from '@hapiness/ng-elements-loader';
import { MadeWithLoveComponent } from './made-with-love.component';

@NgModule({
  imports: [
    CommonModule
  ],
  declarations: [
    MadeWithLoveComponent
  ],
  entryComponents: [
    MadeWithLoveComponent
  ],
  exports: [
    MadeWithLoveComponent
  ]
})
export class MadeWithLoveModule implements WithCustomElementComponent {
  customElementComponent: Type<MadeWithLoveComponent> = MadeWithLoveComponent;
}

Note: Your module must implement WithCustomElementComponent interface exposed by @hapiness/ng-elements-loader and, component must be declared inside entryComponents and declaration meta-data of NgModule.

- Dependencies

The minimum package.json file for your module is described below:

projects/made-with-love/package.json:

{
  "name": "made-with-love",
  "version": "1.0.0",
  "peerDependencies": {
    "@hapiness/custom-elements-loader": "^6.3.1"
  }
}

If your module has to have others dependencies not installed automatically by @hapiness/custom-elements-loader like explained in installation, you must add them in dependencies section.

- Publish your module

Your custom-element module is now ready to be used so you have to publish it before use it in your application.

Back to top

2) made-with-love custom element in your JavaScript application

Create a JavaScript application with your module and @hapiness/ng-elements-loader in dependencies.

Install all dependencies your module must have if not already installed.

- Application contains made-with-love custom element

We create a HTMLfile with our custom element inside.

index.html:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">
    <title>Web Component</title>
</head>
<body>
<div>
    <made-with-love name="Hapiness Framework" url="https://github.com/hapinessjs/" size="2"></made-with-love>
</div>

<script src="./main.js" type="text/javascript"></script>
</body>
</html>

main.js file contains all JavaScript elements to use ElementsLoader and it's built with webpack.

main.ts

// POLYFILLS
import 'zone.js/dist/zone';
import 'document-register-element';

import { ElementsLoader } from '@hapiness/custom-elements-loader';
import { MadeWithLoveModule } from 'made-with-love';

ElementsLoader.loadContainingCustomElements(
    {
        selector: 'made-with-love',
        module: MadeWithLoveModule
    }
).subscribe(undefined, e => console.error(e));
- Explanation

The creation of the custom element happens directly inside HTML file with all attributes we want to display:

<made-with-love name="Hapiness Framework" url="https://github.com/hapinessjs/" size="2"></made-with-love>

Loading of the component happens inside main.ts file.

  • Add required polyfills
import 'zone.js/dist/zone';
import 'document-register-element';
  • Additional polyfills can be added if needed:
/** IE9, IE10 and IE11 requires all of the following polyfills. **/
// import 'core-js/es6/symbol';
// import 'core-js/es6/object';
// import 'core-js/es6/function';
// import 'core-js/es6/parse-int';
// import 'core-js/es6/parse-float';
// import 'core-js/es6/number';
// import 'core-js/es6/math';
// import 'core-js/es6/string';
// import 'core-js/es6/date';
// import 'core-js/es6/array';
// import 'core-js/es6/regexp';
// import 'core-js/es6/map';
// import 'core-js/es6/weak-map';
// import 'core-js/es6/set';

/** IE10 and IE11 requires the following for NgClass support on SVG elements */
// import 'classlist.js';  // Run `npm install --save classlist.js`.

/** IE10 and IE11 requires the following for the Reflect API. */
// import 'core-js/es6/reflect';
  • We call loadContainingCustomElements method of ElementsLoader from @hapiness/custom-elements-loader. This method takes in parameter CustomElementModuleSelector or CustomElementModuleSelector[] from @hapiness/ng-elements-loader.
export interface CustomElementModuleSelector {
    selector: string;
    module: Type<any>;
}

Selector is the custom tag of your custom element and module is the Angular module contains the component.

- Show the result

Launch your application and you will see your custom element displayed inside your JavaScript application:

Made with ♥ by Hapiness Framework

Back to top

3) Custom element with custom event

In the previous component we have created only @Input properties but sometimes, you'll want to emit event from your custom element to the DOM with @Ouput properties.

- Custom element

Here an example of a component emits event to its parent:

projects/hello-world/src/lib/hello-world.component.ts:

import { Component, EventEmitter, OnInit, Output, ViewEncapsulation } from '@angular/core';

@Component({
  selector: 'hello-world',
  templateUrl: './hello-world.component.html',
  styleUrls: ['./hello-world.component.scss'],
  encapsulation: ViewEncapsulation.Native
})
export class HelloWorldComponent implements OnInit {
  private _sayHello$: EventEmitter<string>;

  constructor() {
    this._sayHello$ = new EventEmitter<string>();
  }

  ngOnInit() {
  }
  
  @Output('sayHello')
  get sayHello$(): EventEmitter<string> {
    return this._sayHello$;  
  }

  sayHello() {
    this._sayHello$.emit('Hello World');
  }
}

projects/hello-world/src/lib/hello-world.component.html:

<div>
  <button type="button" (click)="sayHello()">Say Hello with Event</button>
</div>
- Use it in your application

To use it and receive event, you must do this:

index.html:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">
    <title>Web Component</title>
</head>
<body>
<div>
    <hello-world></hello-world>
</div>

<script src="./main.js" type="text/javascript"></script>
</body>
</html>

We set a listener to catch sayHello event and do what we want:

main.ts

// POLYFILLS
import 'zone.js/dist/zone';
import 'document-register-element';

import { ElementsLoader } from '@hapiness/custom-elements-loader';
import { HelloWorldModule } from 'hello-world';

ElementsLoader.loadContainingCustomElements(
    {
        selector: 'hello-world',
        module: HelloWorldModule
    }
).subscribe(undefined, e => console.error(e));

document.querySelector('hello-world').addEventListener('sayHello', (event: any) => alert(event.detail));

Back to top

Change History

  • v6.3.1 (2018-06-20)
    • Delete ShadowDomV1Renderer factory because not compatible with multi-components
  • v6.3.0 (2018-06-20)
    • Use ShadowDomV1Renderer factory from @hapiness/ng-shadow-dom-renderer to fix angular issue #24397
    • Latest packages' versions
    • Documentation
  • v6.1.1 (2018-06-12)
    • Downgrade document-register-element to v1.8.1 to fix angular issue #24390
    • Latest packages' versions
    • Documentation
  • v6.1.0 (2018-06-04)
    • Expose BrowserAnimationsModule instead of BrowserModule to support module with animations.
    • Fix configuration in ng-package*.json
    • Latest packages' versions
    • Documentation
  • v6.0.3 (2018-05-25)
    • Angular v6.0.3+
    • Documentation
  • v6.0.2 (2018-05-13)
    • Delete barrels
    • Documentation
  • v6.0.1 (2018-05-11)
    • Angular v6.0.1+
    • Documentation
  • v6.0.0 (2018-05-07)
    • Angular v6.0.0+
    • Implementation of ElementsLoader factory
    • Documentation

Back to top

Maintainers

tadaweb
Julien FauvilleAntoine GomezSébastien RitzNicolas Jessel

Back to top

License

Copyright (c) 2018 Hapiness Licensed under the MIT license.

Back to top

Keywords

FAQs

Last updated on 20 Jun 2018

Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc