custom elements (Web Components)
Senior Software Engineer @ Commonwealth Bank
React Champion @ CBA Digital
SPA (Single Page Application)
Angular elements are Angular components packaged as custom elements, a web standard for defining new HTML elements in a framework-agnostic way.
HTML Template | <template> and <slot>, <ng-template> and <ng-content> |
Shadow DOM | Encapsulation for style and markup |
Custom Elements | Designing and using new types of DOM elements |
---|
npm install @webcomponents/custom-elements
class MyElement extends HTMLElement {}
customElements.define("my-element", MyElement);
<my-element></my-element>
Similar: Angular Component or React.createElement()
class DangerButton extends HTMLButtonElement {}
customElements.define(
"danger-button",
DangerButton,
{ extends: "button" }
);
<danger-button></danger-button>
Similar: Angular Directive or React.createElement()
class MyElement extends HTMLElement {
// ngOnInit()
connectedCallback() {}
// ngOnDestroy()
disconnectedCallback() {}
}
class HelloWorld extends HTMLElement {
name: string;
static get() observedAttributes = ["name"];
attributeChangedCallback(key, oldValue, newValue) {
if (oldValue !== newValue) {
this.name = newValue;
}
}
set name(value) {}
get name() {}
}
<hello-world name="Leo Caseiro"></hello-world>
Similar: Angular @Input() and @HostBinding()
Similar: React props
class DangerButton extends HTMLButtonElement {
onClick() {
this.dispatchEvent(
new CustomEvent("show-validation",
{ form: isValid }
)
);
}
}
const dangerBtn = document.querySelector('danger-button');
dangerBtn.addEventListener("show-validation", event => { ... });
Similar: @Output()
ng add @angular/elements
{
"target": "es2015"
}
In browsers that support Custom Elements natively, the specification requires developers to use ES2015 classes to define Custom Elements.
Bootstrap
import { BrowserModule } from '@angular/platform-browser';
import { createCustomElement } from '@angular/elements';
@NgModule({
imports: [BrowserModule],
declarations: [MyAngularElementComponent],
entryComponents: [MyAngularElementComponent]
})
export class AppModule {
constructor(private injector: Injector) {}
ngDoBootstrap() {
customElements.define("my-angular-element",
createCustomElement(MyAngularElementComponent,
{ injector: this.injector }
)
);
}
}
@Component({
selector: 'danger-button',
template: `<slot></slot>`, // similar ng-content
encapsulation: ViewEncapsulation.Native // wait ng7 and Ivy
})
export class DangerButtonComponent {}
Slots + Shadom DOM - Experimental
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.myRef = React.createRef();
}
render() {
return <my-web-component ref={this.myRef}></my-web-component>;
}
}
const node = this.myRef.current;
node.messages = [];
Uncaught Error: Error trying to diff '[object Object],[object Object]'. Only arrays and iterables are allowed
const listItems = numbers.map((number) =>
<li key={number.toString()}>
{number}
</li>
);
npm install web-react-components