I want to make a drop-down menu and that when clicking on the input, the menu is displayed with a toggle that removes or places the 'hidden' class
I have this method
toggleMenu() {
this.classList.toggle("hidden");
}
And here the template.
render(){
return html`
<input @click="${this.toggleMenu}" type="button">
<ul class="hidden">
<slot></slot>
</ul>
`;
}
One straightforward solution is to add a property to your custom element, e.g. open
, that is toggled in your toggleMenu
method:
static get properties() {
return {
open: { type: Boolean },
};
}
constructor() {
super();
this.open = false;
}
toggleMenu() {
this.open = !this.open;
}
Then in your render
method set the <ul>
's class
attribute based on the value of this.open
:
render(){
return html`
<button @click=${this.toggleMenu} type="button">Toggle</button>
<ul class=${this.open ? '' : 'hidden'}>
<slot></slot>
</ul>
`;
}
You can see this working in the below snippet:
// import { LitElement, css, html } from 'lit-element';
const { LitElement, css, html } = litElement;
class DropDownMenu extends LitElement {
static get properties() {
return {
open: { type: Boolean },
};
}
static get styles() {
return css`
ul.hidden {
display: none;
}
`;
}
constructor() {
super();
this.open = false;
}
toggleMenu() {
this.open = !this.open;
}
render(){
return html`
<button @click=${this.toggleMenu} type="button">Toggle</button>
<ul class=${this.open ? '' : 'hidden'}>
<slot></slot>
</ul>
`;
}
}
customElements.define('drop-down-menu', DropDownMenu);
<script src="https://bundle.run/lit-element@2.2.1"></script>
<drop-down-menu>
<li>Item 1</li>
<li>Item 2</li>
</drop-down-menu>
If you want to apply additional classes to the <ul>
you'll want to look into the classMap
function as described in the LitElement docs.
Alternatively, you can add reflect: true
to the open
property declaration, which lets you show or hide the <ul>
using CSS alone, rather than setting its class
in render
:
static get properties() {
return {
open: {
type: Boolean,
reflect: true,
},
};
}
static get styles() {
return css`
ul {
display: none;
}
:host([open]) ul {
display: block;
}
`;
}
Here it is in a working snippet:
// import { LitElement, css, html } from 'lit-element';
const { LitElement, css, html } = litElement;
class DropDownMenu extends LitElement {
static get properties() {
return {
open: {
type: Boolean,
reflect: true,
},
};
}
static get styles() {
return css`
ul {
display: none;
}
:host([open]) ul {
display: block;
}
`;
}
constructor() {
super();
this.open = false;
}
toggleMenu() {
this.open = !this.open;
}
render(){
return html`
<button @click=${this.toggleMenu} type="button">Toggle</button>
<ul>
<slot></slot>
</ul>
`;
}
}
customElements.define('drop-down-menu', DropDownMenu);
<script src="https://bundle.run/lit-element@2.2.1"></script>
<drop-down-menu>
<li>Item 1</li>
<li>Item 2</li>
</drop-down-menu>
Both of these are common approaches and the best one for your application will depend on your use case and personal preferences.