<custom-app>
<h1>Custom apps</h1>
<p>
This is some "light DOM" inside a <tt>custom-app</tt> Custom Element.</p>
<p>The following list is composed of <tt>custom-view</tt> Custom Elements. They're clickable and react to their <tt>color</tt> attribute changing:
</p>
<ul>
<li><custom-view color="red">Red</custom-view></li>
<li><custom-view color="green">Green</custom-view></li>
<li><custom-view color="blue">Blue</custom-view></li>
</ul>
<p>
Color is changed by calling <tt>setColor</tt> in the <tt>custom-app</tt> Element:
</p>
<div class="selected-color"></div>
</custom-app>
// This element renders a clickable span that
// calls `setColor` on a parent element of
// type `CustomApp`.
// This could extend Link, if we wanted extra
// features like "visited", or maybe free
// cursor:pointer styling, but then you need to
// use the custom-view differently, as:
// <a is="custom-view" color="...">...</a>
// (which to me looks worse)
class CustomView extends HTMLElement {
// react to changes in the 'color' attribute.
static get observedAttributes() { return ['color']; }
constructor() {
super();
console.log('Initializing custom-view element');
}
connectedCallback() {
this.style.cursor = "pointer";
this.style.color = this.getAttribute('color');
this.addEventListener('click', function(e) {
let target = e.target; // or "this"
let color = target.getAttribute('color');
// Find parent of type custom-app, and
// call method there...
if (!this._parentApp) {
// Locating the parent app is easy
// This would need to be re-computed
// (or nullified) when the element is
// disconnected.
this._parentApp = e.target.closest('custom-app');
}
this._parentApp.setColor(color);
});
}
attributeChangedCallback(name, oldValue, newValue) {
// If the "color" attribute is changed from
// the DOM...
if (name === 'color') {
this.style.color = newValue;
}
}
}
class CustomApp extends HTMLElement {
constructor() {
super();
console.log('Initializing custom-app element');
}
connectedCallback() {
// Grab the style here!
let style = new CSSStyleSheet();
style.insertRule('.selected-color { background-color: #ddd }');
document.adoptedStyleSheets = [style];
// for laters
this._target = this.querySelector('.selected-color');
}
attributeChangedCallback(name, oldValue, newValue) {
console.log(`${name} changed from ${oldValue} to ${newValue}`);
}
setColor(newColor) {
//...
Please Whitelist JSFiddle in your content blocker.
Help keep JSFiddle free for always by one of two ways:
Whitelist JSFiddle in your content blocker (two clicks)
Go PRO and get access to additional PRO features →
Join the 4+ million users, and keep the JSFiddle dream alive.
Ad-free
All ads in the editor and listing pages are turned completely off.
Use pre-released features
You get to try and use features (like the Palette Color Generator) months before everyone else.
Fiddle collections
Sort and categorize your Fiddles into multiple collections.
Private collections and fiddles
You can make as many Private Fiddles, and Private Collections as you wish!
Console
Debug your Fiddle with a minimal built-in JavaScript console.