document.querySelector() always selects the element with the class "Open" even after it has been removed and replaced with the class "Close" | Vue3 js

Viewed 23

So I was trying to find a Vue Solution of the jQuery SlideUp() and slideDown() functionality. And I have run into a problem while creating the same for my Side Bar Menu Open and Close funtion. See my code below:

UPDATE: Here's the stackblitz link to the problem: https://stackblitz.com/edit/vue-lvjxmz

I'd really appreciate if someone helps me to solve this problem. Thanks.

export default {

  mounted() {
       let hasSubmenu = Array.from(document.querySelectorAll(".hasSubmenu.close"));//Select all hasSubmenu
       let self = this;
       hasSubmenu.forEach(function (el) {//Show Hide Submenu Based On Clicks
            el.addEventListener("click", self.menuOpen.bind(this, el));

        });
  },
  methods:{
          //Menu Opener Function
          menuOpen(el){
              let ul = el.querySelector("ul");
              ul.style.height = `${ul.scrollHeight}px`;
              el.classList.remove("close");//Remove The Class "close"
              el.classList.add("open");// add the class "open"

              this.menuClose();//Call this function to close the menu

          },
          //Menu Closer Function
          menuClose(){
              console.log(document.querySelector(".hasSubmenu.open"));//Log the Selected Element
              document.querySelector(".hasSubmenu.open").addEventListener("click", function (e) {
                  e.currentTarget.querySelector("ul").style.height = "0px";
                  e.currentTarget.classList.remove("open");
                  e.currentTarget.classList.add("close");
              });
          }
  },
}
<ul id="main-nav">
  <li class="hasSubmenu close">
    <a href="#" class="menuItem"><div> Main Menu One</div></a>
    <ul style="height: 0px">
      <li>
        <a href="#" class="py-3"> Sub Menu One</a>
       </li>
       <li>
        <a href="#" class="py-3"> Sub Menu Three</a>
       </li>
     </ul>
   </li>
</ul>

So what we are doing here is: we are first selecting all the hasSubmenu items with the class close has in it. Then firing the click event where the menu opens and replace the class close with "open". Then we are calling the menuClose function where we are selecting the element which has the .open class. then firing another click event when the menu closes and removes the class .open and adds .close again.

The problem is somehow the menuClose function keeps selecting the element as if it was pointing to the hasSubmenu element and caching it in, it doesn't matter whether the class has been changed or not. I mean, even after the .open class has been removed on the click event it stills selecting it and thus clicking on the menuItem after the first 2 clicks the menuOpen function first opens the menu then calls the menuClose function and immediately closes the menu again although menuClose functionality only added to document.querySelector(".hasSubmenu.open"). As if, it first selected the element itself not the class and cached it in.

1 Answers

Okay, as per James Reply I have managed to solve the problem in another way. So the solution goes as below:

// Simply write one function and check if the submenu's 
// height is 0px or not. Based on that write your 
// open and close logics
menuOpenClose(el){
    let ul = el.querySelector("ul");
    let getHeight = ul.style.height;
    console.dir(getHeight);
    if (getHeight == '0px' || !getHeight.length) {
        ul.style.height = `${ul.scrollHeight}px`;
        el.classList.remove("close");
        el.classList.add("open");
    } else{
        ul.style.height = `0px`;
        el.classList.remove("open");
        el.classList.add("close");
    }
}

Related