6

Is it possible to use the simple menu animation from W3School in Stencil.js?

https://www.w3schools.com/howto/tryit.asp?filename=tryhow_css_menu_icon_js

I'm trying to set the styling on a click event, but I can't make it work. The event is fireing but I can't set the class.

In my .tsx:

import { Component, Prop, h } from '@stencil/core';

@Component({
  tag: 'topbar-component',
  styleUrl: 'topbar-component.css',
  shadow: true
})

export class Topbar {

  private menuToggle(e) {
    return (
      e.classList.toggle("change");
    );
  }

  render() {
    return (
      <div class="topbar-menu">
        <div class="container" onClick={(e) => this.menuToggle(e)}>
            <div class="bar1"></div>
            <div class="bar2"></div>
            <div class="bar3"></div>
        </div>
      </div>
    )
  }
}

In my css:

.bar1, .bar2, .bar3 {
  width: 35px;
  height: 5px;
  background-color: #333;
  margin: 6px 0;
  transition: 0.4s;
}

.change .bar1 {
  -webkit-transform: rotate(-45deg) translate(-9px, 6px);
  transform: rotate(-45deg) translate(-9px, 6px);
}

.change .bar2 {opacity: 0;}

.change .bar3 {
  -webkit-transform: rotate(45deg) translate(-8px, -8px);
  transform: rotate(45deg) translate(-8px, -8px);
}

I get error: Uncaught TypeError: Cannot read property 'toggle' of undefined

Johan Byrén
  • 890
  • 2
  • 13
  • 28
  • 1
    for all it's worth (because the post is already a bit older...): you are trying to get the classList of an event. But the class list sits on the .targetElement of the event, like it is shown in the last example. – yogibimbi Jun 06 '22 at 12:47

3 Answers3

10

You could do it using a state property:

import { Component, Prop, State, h } from '@stencil/core';

@Component({
  tag: 'topbar-component',
  styleUrl: 'topbar-component.css',
  shadow: true
})

export class Topbar {

  @State() isMenuOpen: boolean = false;

  private menuToggle() {
    this.isMenuOpen = !this.isMenuOpen;
  }

  render() {
    return (
      <div class="topbar-menu">
        <div class={{ container: true, change: this.isMenuOpen }}" onClick={(e) => this.menuToggle(e)}>
            <div class="bar1"></div>
            <div class="bar2"></div>
            <div class="bar3"></div>
        </div>
      </div>
    )
  }
}
Thomas
  • 8,426
  • 1
  • 25
  • 49
2

I made it work. I found the classlist at last.

So just add this to your menuToggle()

  private menuToggle(e) {
    return (
      e.currentTarget.classList.toggle("change")
    );
  }
Johan Byrén
  • 890
  • 2
  • 13
  • 28
  • Thanks a lot, It worked for me. I had to add the class in parent element of clicked button. – Anand Nov 22 '22 at 07:54
0

I think the following code can be usefuel for handling your question:

    import { Component, Prop, h } from '@stencil/core';
    @Component({
      tag: 'topbar-component',
      styleUrl: 'topbar-component.css',
      shadow: true
    })
    
    export class Topbar {
    
      private menuToggle() {
        this.isMenuOpen = !this.isMenuOpen
      }

  render() {
    return (
      <div class="topbar-menu">
         {this.isMenuOpen
                ?
                <div class=container change" onClick={() => this.menuToggle()}>
                <div class="bar1"></div>
                <div class="bar2"></div>
                <div class="bar3"></div>
               </div>
                :
               <div class=container" onClick={() => this.menuToggle()}>
                <div class="bar1"></div>
                <div class="bar2"></div>
                <div class="bar3"></div>
               </div>
              }
      </div>
    )
  }
}
        

   
amir tbi
  • 320
  • 2
  • 14