JSFiddle - React, Tailwind, and code Playground
by 2Yootz
HTML
<h1>Web Components</h1>
<h3>Intro</h3>
<div>This is an example to showcase native web componets. In this example you will see a custom HTML element, the template tag (<span class="highlight"><template></span>) and Shadow DOM. The timestamp on the bottom of the page is proof that button requests aren't simply reloading the page.</div>
<br />
<h3>Demonstration</h3>
<div>I have a comment box on the page. Clicking on the Add button will include another by using a custom html element <span class="highlight"><page-comment></page-comment></span>. When this renders it automatically calls a <span class="highlight">createdCallback</span>, which reads the template tag contents and display it. The markup used to create the textareas and their labels are identical. Notice that the template tag keeps everything inert. For instance, inline javascript and css do not have any impact until the template is read and contents truly placed in DOM. When it is injected the CSS doesn't override the defaults on the page. The span tag normally has inline behavior. But in the template it is being assiged to <b>block</b> so that the label appears above the textarea. Shadow DOM isolates that style from affecting the rest of the page.</div>
<br />
<br />
<label><span>Comment:</span>
<textarea></textarea>
</label>
<br />
<br />
<button id="btnCommentSection">Add Textarea</button>
<div id="divCommentSection"></div>
<br />
<div id="divPageRenderedStamp"></div>
<!-- ***** TEMPLATE AREA IS HERE ****** -->
<template id="myTemplate">
<style>
span {
display:block;
}
</style>
<label><span>Comment:</span>
<textarea></textarea>
</label>
<script>
alert('Ready for Comment!');
</script>
</template>
CSS
h1 {
text-align:center;
font-size:1.833em;
}
#divPageRenderedStamp {
margin-top:1.667em;
font-size:0.917em;
font-weight:bold;
}
body {
font-family: arial;
font-size:14px;
}
.highlight {
background-color:#FFFFCC;
}
JavaScript
//setting timestamp on page load
document.getElementById("divPageRenderedStamp").innerHTML = "Page Rendered: " + new Date().toISOString();
//button click event
var btn = document.getElementById("btnCommentSection");
btn.addEventListener("click", function (e) {
var dest = document.getElementById("divCommentSection");
this.style.display = 'none';
//dest.appendChild(new pgcomment()); //works too!!
dest.innerHTML = '<page-comment></page-comment>';
});
//Initializing new html attributes
var commentProto = Object.create(HTMLElement.prototype);
//once it renders then call this function
commentProto.createdCallback = function () {
var shadow = this.createShadowRoot(); //encapsulating everything into its own ** SHADOW DOM **
//reading the template and showing it within the custom tags
var template = document.querySelector("#myTemplate");
var clone = document.importNode(template.content, true);
shadow.appendChild(clone);
};
//registering the <page-comment> tag
var pgcomment = document.registerElement('page-comment', {
prototype: commentProto
});