Skip to content

Instantly share code, notes, and snippets.

@denisos
Created December 23, 2022 20:03
Show Gist options
  • Save denisos/1bbf9336171379bdd7e19b50e2cd8524 to your computer and use it in GitHub Desktop.
Save denisos/1bbf9336171379bdd7e19b50e2cd8524 to your computer and use it in GitHub Desktop.
/*
* ShadowComponent a simple Web Component to render content passed and wrap it in a shadow dom
* why web component? to create shadow dom and isolate html & styles passed in content prop
* usage:
* <shadowcomponent-wc content={html} />
*
* ShadowComponent will rerender when the value passed to content changes.
* content passed is trusted and security is the responsibility of the caller
* references: https://css-tricks.com/building-interoperable-web-components-react/
* https://www.youtube.com/watch?v=vLkPBj9ZaU0
*/
class ShadowComponent extends HTMLElement {
private shadow: ShadowRoot;
public constructor() {
super();
// create a shadowRoot (used later in render)
this.shadow = this.attachShadow({mode: 'open'});
}
// gets content prop passed in
public get content() {
return this.getAttribute('content') || '';
}
// when content changes update it
public set content(val: string) {
this.setAttribute('content', val);
}
// observe the content prop
public static get observedAttributes() {
return ['content'];
}
// and when the observed content prop changes, re-render
// also passed oldValue and newValue params but we don't use here
public attributeChangedCallback(name: string) {
if (name === 'content') {
// "this" is the web component itself
this.render();
}
}
// fired when this component is added to the dom
public connectedCallback() {
this.render();
}
public render() {
this.shadow.innerHTML = `${this.content}`;
}
}
// register the component (once only) with the name shadowcomponent-wc
if (!customElements.get('shadowcomponent-wc')) {
customElements.define('shadowcomponent-wc', ShadowComponent);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment