i am trying to create a dropdown menu using directives from angularJS and so far it looks like this:
<div class="dropdown">
<button class="button">Dropdown</button>
<ul>
<li><a>Menu Item 1</a></li>
<li><a>Menu Item 2</a></li>
</ul>
</div>
This is the html layout and this is the directive so far:
myApp.directive('dropdown', function($parse) {
return {
restrict: "C",
link: function(scope, elem, attr) {
var isDisabled = $parse(attr.ngDisabled);
var toggleMenu = function() {
if(!elem.hasClass('dropdown-active') && !isDisabled(scope))
elem.addClass('dropdown-active');
else
elem.removeClass('dropdown-active');
};
elem.bind('click', toggleMenu);
}
}
});
So far it works, when i press on the button, the list opens and when i press again it closes but now i have a problem.. i need to make it to close when i press anywhere outside the dropdown.
Can i do that without using jQuery? I am trying to do this project with just AngularJS.
Thank you in advance, Daniel.
Link to Plunker (here i have a problem, when i press on a dropdown, the other one doesnt close)
i am trying to create a dropdown menu using directives from angularJS and so far it looks like this:
<div class="dropdown">
<button class="button">Dropdown</button>
<ul>
<li><a>Menu Item 1</a></li>
<li><a>Menu Item 2</a></li>
</ul>
</div>
This is the html layout and this is the directive so far:
myApp.directive('dropdown', function($parse) {
return {
restrict: "C",
link: function(scope, elem, attr) {
var isDisabled = $parse(attr.ngDisabled);
var toggleMenu = function() {
if(!elem.hasClass('dropdown-active') && !isDisabled(scope))
elem.addClass('dropdown-active');
else
elem.removeClass('dropdown-active');
};
elem.bind('click', toggleMenu);
}
}
});
So far it works, when i press on the button, the list opens and when i press again it closes but now i have a problem.. i need to make it to close when i press anywhere outside the dropdown.
Can i do that without using jQuery? I am trying to do this project with just AngularJS.
Thank you in advance, Daniel.
Link to Plunker (here i have a problem, when i press on a dropdown, the other one doesnt close)
http://plnkr.co/edit/OrfUVg8KsOhAxqLwn1li?p=preview
Share Improve this question edited May 6, 2014 at 0:57 Pacuraru Daniel asked May 5, 2014 at 23:16 Pacuraru DanielPacuraru Daniel 1,2059 gold badges31 silver badges57 bronze badges 4- 1 My guess would be you may need to copy jqueryui's technique and create a full page invisible div that sits under the dropdown menu div with an onclick close. – mnsr Commented May 5, 2014 at 23:54
- 2 You should look at the source for the dropdown in ui-bootstrap: github./angular-ui/bootstrap/blob/master/src/dropdown/… For example, they close the dropdown if the user hits the ESC key. Perhaps you could model yours after this. Better yet, why not just use their dropdown? You don't actually have to use bootstrap, you can replace or override their templates and just assign your own classes. – aet Commented May 6, 2014 at 0:37
- Bind an event onto the window on toggleIn, and unbind it on toggleOut. In the event check to see if the event target is the directive element, if not, toggleOut – Zack Argyle Commented May 6, 2014 at 2:16
- how can i see into the target event if it's the element ? – Pacuraru Daniel Commented May 6, 2014 at 11:49
5 Answers
Reset to default 1I found a way to make this happen, what i did is i use a class 'active-recent' and than just close all the opened menus expect the one that has this class, and just right after, i remove the recent class, so next time when i press on other dropdown, this last one closes aswell.
myApp.directive('dropdown', function($document) {
return {
restrict: "C",
link: function(scope, elem, attr) {
elem.bind('click', function() {
elem.toggleClass('active');
elem.addClass('active-recent');
});
$document.bind('click', function() {
if(!elem.hasClass('active-recent')) {
elem.removeClass('active');
}
elem.removeClass('active-recent');
});
}
}
});
http://plnkr.co/edit/wzJkSb0bU53t7liOoVJZ?p=preview
This is from something i made as a test about a year back which originally didn't have the 'click anywhere to close' functionality in it. I just forked it and used JqueryUI's technique, and created an overlay div that has an ng-show, and ng-click. It's a bit rough, and you can neaten it up. But it works:
app.directive("dropdown", function() {
return {
restrict: 'A',
link: function(scope) {
scope.showDropdown = function() {
if (scope.showList) {
scope.showList = false;
scope.overlay = false;
}
else {
scope.showList = true;
scope.overlay = true;
}
}
}
}
});
Dropdown HTML:
<div class="overlay" ng-show="overlay" ng-click="showList = false;overlay = false;"></div>
<div class="btn btn-info" ng-click="showDropdown()" dropdown>{{selectedCar}} <i class="caret"></i></div>
<div class="drop-down" ng-show="showList" dropdown-options ng-transclude>
<ul>
<li ng-repeat="car in viewModel"><a href="" ng-click="selectItem(car.n)">{{car.n}}</a></li>
</ul>
</div>
</div>
overlay CSS:
.overlay { background:transparent; width:100%; height:100%; position:absolute; top:0; left:0; }
Plunkr:
http://plnkr.co/edit/5IpClw?p=preview
I have used a dropdown in which if you take the cursor outside the dropdown it closes automatically.You can try this
<ul class="nav navbar-nav">
<li class="dropdown" >
<button class="dropdown-toggle form-control" data-toggle="dropdown" >
{{selectedParent.displayName}}<span class="caret"></span>
</button>
<div class="dropdown-menu">
/*Your drop down list here*/
</div>
</li>
</ul>
Hope it's helpful!
The angular-dropdowns directive is another way to go. Its available from github at
https://github./jseppi/angular-dropdowns
It can be used in a select option style or as a button with a menu of dropdowns.
warning: changeEvent function must be inside controller for better modification without touching directive.
var app = angular.module('main', []);
app.controller('exampleCtrl', exampleCtrl);
exampleCtrl.$inject = [];
function exampleCtrl(){
var vm = this;
vm.testData = ['one', 'two', 'three'];
vm.selectedItem = vm.testData[0];
vm.changeEvent = function (item){
vm.selectedItem = item;
}
}
app.directive('uiDropdown', uiDropdown);
uiDropdown.$inject=[];
function uiDropdown (){
return {
restrict: 'A',
link: function(scope, element, attr, ctrl) {
var ulDropdown = element.next("[ui-dropdown-data]");
element.on('click', function() { // Click on ui-dropdown
ulDropdown[0].style.display = ulDropdown[0].style.display === 'none' ? 'block' : 'none';
});
ulDropdown.on('click', function (data) { //click on ui-dropdown-data
ulDropdown[0].style.display = 'none';
});
element.parent().on('mouseleave', function () { // leave parent div
ulDropdown[0].style.display = 'none';
});
}
};
}
<script src="https://ajax.googleapis./ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<script src="https://ajax.googleapis./ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="main">
<div ng-controller="exampleCtrl as vm">
<div ui-dropdown style="cursor:pointer; border:1px solid; width:50px;">{{vm.selectedItem}}</div>
<ul style="display: none" ui-dropdown-data>
<li style="border:1px dotted;width:50px; cursor:pointer" ng-repeat="item in vm.testData" ng-click="vm.changeEvent(item)">{{item}}</li>
</ul>
<div>
</div>