Reputation: 1937
I needed to write my dropdown menu in javascript because there are several aspects that cannot be done with CSS. I came across this bug when I hover over my menu item, submenu pops up, I click on an element and it starts flickering.
I know it's because I'm still within that element which triggers mouseenter again. What can I do in this case?
I don't want to set up a timer to wait and then reopen the dropdown menu again...
angular.module('app',[])
.controller('mainCtrl', function() {
var vm = this;
vm.showSubmenu = false;
vm.toggleMenu = function() {
vm.showSubmenu = !vm.showSubmenu;
}
vm.changeState = function() {
//$state.go('blablabla');
vm.showSubmenu = false;
}
})
.submenu {
background: lightblue;
position: absolute;
top: 45px;
left: 0;
padding: 20px;
line-height: 20px;
visibility: hidden;
}
.submenu.active-sub {
visibility: visible;
}
.menu {
list-style-type: none;
}
ul li {
background: grey;
line-height: 30px;
width: 150px;
}
.submenu ul {
position: relative;
float: left;
left: 0;
}
<html ng-app="app">
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.7.5/angular.min.js"></script>
</head>
<body>
<div ng-controller="mainCtrl as vm">
<ul class="menu">
<li ng-mouseenter="vm.toggleMenu()" ng-mouseleave="vm.toggleMenu()">OPEN SUBMENU
<div class="submenu" ng-class="{'active-sub':vm.showSubmenu}">
<ul>
<li><a href="#" ng-click="vm.changeState()">Link 1</a></li>
<li><a href="#" ng-click="vm.changeState()">Link 2</a></li>
<li><a href="#" ng-click="vm.changeState()">Link 3</a></li>
</ul>
</div>
</li>
</ul>
</div>
</body>
</html>
Upvotes: 0
Views: 1437
Reputation: 689
Why don't you just add hideMenu() and showMenu() functions, since that is what you want. You want to hide the menu in mouseleave event and show the menu in mouseenter.
If you don't want to write more code within the click event you could also call hideMenu() instead of a new function.
Edit (explanation of the problem)
It's because of the firering events. So basically what happens is the following.
vm.showSubmenu = false
vm.showSubmenu = !vm.showSubmenu; // gets true
changeState()
sets vm.showSubmenu = false;
changeState()
method, the mouseleave event negates the variable, so the submenu gets visible again, the mouseenter gets fired, the variable gets false and so on...angular.module('app',[])
.controller('mainCtrl', function() {
var vm = this;
vm.showSubmenu = false;
vm.hideMenu = function() { vm.showSubmenu = false; }
vm.showMenu = function() { vm.showSubmenu = true; }
vm.click = function(){ vm.hideMenu(); }
})
.submenu {
background: lightblue;
position: absolute;
top: 45px;
left: 0;
padding: 20px;
line-height: 20px;
visibility: hidden;
}
.submenu.active-sub {
visibility: visible;
}
.menu {
list-style-type: none;
}
ul li {
background: grey;
line-height: 30px;
width: 150px;
}
.submenu ul {
position: relative;
float: left;
left: 0;
}
<html ng-app="app">
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.7.5/angular.min.js"></script>
</head>
<body>
<div ng-controller="mainCtrl as vm">
<ul class="menu">
<li ng-mouseenter="vm.showMenu()" ng-mouseleave="vm.hideMenu()">OPEN SUBMENU
<div class="submenu" ng-class="{'active-sub':vm.showSubmenu}">
<ul>
<li><a href="#" ng-click="vm.click()">Link 1</a></li>
<li><a href="#" ng-click="vm.click()">Link 2</a></li>
<li><a href="#" ng-click="vm.click()">Link 3</a></li>
</ul>
</div>
</li>
</ul>
</div>
</body>
</html>
Upvotes: 1