简体   繁体   中英

How can I make my 'li' click on Services to produce a drop down menu

I am trying to produce a custom navigation bar. Clicking on the Services or Plans list items should produce a drop down menu. However currently when you click on the items it does not work as expected instead, it produces an error that says: 'cannot read property contains of undefined'. I simply want to be able to select the sub-menu class and add sub-menu-active class(which I have set in my CSS to display as block). I have initially set the display property in my CSS file to 'none'.

Here is the select html file I am trying to manipulate

<nav class="custom-navigationbar-container" >
    <ul class="menu">
        <li class="logo"><a href="#">Home</a></li>
        <li class="item"><a href="#">About</a></li>
        <li class="item"><a href="#">Blog</a></li>
        <li class="item special">
            <a tabindex="0">Services <i class="fas fa-sort-down"></i></a>
            <ul class="sub-menu" >
                <li class="sub-item" ><a href="#">Web Design</a></li>
                <li class="sub-item" ><a href="#">Web Development</a></li>
                <li class="sub-item" ><a href="#">SEO</a></li>
                <li class="sub-item" ><a href="#">Digital Marketing</a></li>
            </ul>
        </li>
        <li class="item special has-sub-menu">
            <a tabindex="0">Plans <i class="fas fa-sort-down"></i></a>
            <ul class="sub-menu">
                <li class="sub-item" ><a href="#">Freelancer</a></li>
                <li class="sub-item" ><a href="#">StartUp</a></li>
                <li class="sub-item" ><a href="#">Enterprise</a></li>
            </ul>
        </li>
        <li class="item" ><a href="#">Blog</a></li>
        <li class="item" ><a href="#">Contact</a></li>
        <li class="item button" ><a href="#">Log In</a></li>
        <li class="item button secondary" ><a href="#">Sign Up</a></li>
        <li class="toggle"><a href="#"><i class="fas fa-bars" ></i></a></li>
    </ul>
</nav>

This is the .Js code

const special = document.querySelectorAll(".special");
const specialToggle = function(){
    const subMenu = this.getElementsByClassName('sub-menu');
    if(subMenu.classList.contains(".sub-menu-active")){
        console.log('I am removing sub-menu-active now');
        ul.classList.remove('.sub-menu-active');
    }else{
        console.log('I am adding sub-menu-active now');
        ul.classList.add('.sub-menu-active'); 
    }
    
};

for(const specials of special){
    specials.addEventListener('click', specialToggle)
}

Your main problem is this line:

const subMenu = this.getElementsByClassName('sub-menu');

This will return multiple elements. Or at least it will return a COLLECTION of zero or one elements.

You might consider:

const subMenu = this.getElementsByClassName('sub-menu')[0];

But this will only get the first one, even if you clicked on the second one.

So maybe it's best to return the event in the function, get the target's parent, and find the 'sub-menu' within it. Then you're good to go:

const subMenu = e.target.parentElement.getElementsByClassName('sub-menu')

Here's a working version of the code against a simplified HTML structure:

 const special = document.querySelectorAll(".special"); const specialToggle = function(e){ const subMenu = e.target.parentElement.getElementsByClassName('sub-menu')[0]; if (subMenu == null) { console.log('No sub-menu. Perhaps you have clicked on a child element?'); } else if(subMenu.classList.contains(".sub-menu-active")){ console.log('I am removing sub-menu-active now'); subMenu.classList.remove('.sub-menu-active'); } else{ console.log('I am adding sub-menu-active now'); subMenu.classList.add('.sub-menu-active'); } }; for(const specials of special){ specials.addEventListener('click', specialToggle) }
 <ul class="menu"> <li class="logo"><a href="#">Home</a></li> <li class="item special"> <a tabindex="0">Services <i class="fas fa-sort-down"></i></a> <ul class="sub-menu" > <li class="sub-item" ><a href="#">Web Design</a></li> <li class="sub-item" ><a href="#">Web Development</a></li> </ul> </li> <li class="item special has-sub-menu"> <a tabindex="0">Plans <i class="fas fa-sort-down"></i></a> <ul class="sub-menu"> <li class="sub-item" ><a href="#">Freelancer</a></li> <li class="sub-item" ><a href="#">StartUp</a></li> </ul> </li> </ul>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM