Say I have this thing called a "panel". It contains a hidden section and a button to show it. Easy enough.
However I got a little fancy and decided to use a custom element <custom-panel>
to markup the boundaries for each panel, a <template>
for the contents and <slots>
for the configuration (title, details, etc).
Now I am a little confused as to how to hook up the buttons. The template has CSS that will show/hide the details of the panel if the correct class is set. But how to I set it? I have only figured out how to get to the contents of the template (without the resolved slots) or the custom-panel’s contents (with no template information).
Complete Example:
customElements.define(
'custom-panel',
class extends HTMLElement {
constructor() {
super();
const template = document.getElementById('custom-panel-template');
const templateContent = template.content;
this.attachShadow({
mode: 'open'
}).appendChild(
templateContent.cloneNode(true)
);
}
}
);
<custom-panel>
<span slot="openButtonText">Open Panel 1</span>
<span slot="closeButtonText">Close Panel 1</span>
<span slot="panelName">Panel 1</span>
<div slot="">Panel 1 Details</div>
</custom-panel>
<custom-panel>
<span slot="openButtonText">Open Panel 2</span>
<span slot="closeButtonText">Close Panel 2</span>
<span slot="panelName">Panel 2</span>
<div slot="panelContent">Panel 2 Details</div>
</custom-panel>
<template id="custom-panel-template">
<style type="text/css">
#panel {
display: none;
}
#panel.open {
display: revert;
}
</style>
<!-- how do these get hooked in? -->
<button type="button"><slot name="openButtonText">Default Open Button Text</slot></button>
<button type="button"><slot name="closeButtonText">Default Close Button Text</slot></button>
<fieldset id="panel">
<legend><slot name="panelName">Default Panel Name</slot></legend>
<slot name="panelContent">Default Panel Content</slot>
</fieldset>
</template>
2
Answers
Its your own component, no one is ever going to set multiple Event Listeners to one button.
So use inline Event Handlers instead of
addEventListener
You can then use cleaner DOM creation code with a
createElement( tag, props )
functionNo need for a fancy
<template>
You only need to create a handful DOM elements.You also do not want to set a
[open]
state buried deep inside a class in shadowDOM.State should be set on the Web Component itself as:
<custom-panel open>
:host(:not([open)) fieldset { display:none }
then toggles visibilityAlso read my Dev.To post on
<details-accordion>