Krishna
Krishna

Reputation: 179

closing dropdown single or multiselect when clicking outside

I am trying close my drop downs which are multiselect. below is the code I am trying :

element.bind('click', function (event) {
    event.stopPropagation();
});

$document.bind('click', function () {
    $scope.opened = false;
    $scope.$apply();
});

but once I click outside the drop down window. one click is triggering multiple click event and for each click below block of code is getting called n number of times like = 40, 90 etc I guess it is equal to number of element in the window:

$document.bind('click', function () {
    $scope.opened = false;
    $scope.$apply();
});

I tried even event.stopPropagation() just after document.bind but it did not work.

These chunk of code I have written inside the link function of directive which I created for multiselect.

Upvotes: 1

Views: 4502

Answers (2)

Krishna
Krishna

Reputation: 179

I have solved my problem using below solution for single Select and Multi Select dropdown.

  1. Below solution can be used in production as it does not has any performance impact as such

My Approach of design I have create directive for single select as below:

.directive("selection", ['$document',
        function ($document) {
       -- your variable initialization--
       --any other method if you have like I have --
         $scope.change = function (item) {
          -------- my implementation 
     };
     $scope.selected = function (item) {
         -------- my implementation
    };
//Actual click event should be handled in link function
function link($scope, element, attributes, ngModel) {
   --other methods if you have any--
            element.bind('click', function(event) {
                    $scope.onElementClick = true;
                    $document.on("click", $scope.onClick);
                });

                 $scope.onClick = function (event) {
                    if($scope.onElementClick && $scope.opened)
                    {
                      $scope.onElementClick = false;
                      return;
                    }
                    $scope.opened = false;
                    $scope.$apply(attributes.selection);
                    $document.off("click", $scope.onClick);
                  };
                }
                return {
                restrict: 'E',
                controller: controller,
                link: link,
               scope: true,
               require: "ngModel",
               templateUrl: 'your template file(e.g: filename.tpl.html)'
        };

So above code will bind the click event with document only when you click on any single select drop down and it will unbind as soon as it gets closed because of $document.off("click", $scope.onClick);

for multi select drop down you need to handle special case like drop down should not get closed if you click on the element other wise you can not select more than one option at a time. so you have to stop the propagation of click event if it is clicked inside the element. please make below change in you click event handling inside link function:

.directive("multiSelection", ['$document',
        function ($document) {
       -- your variable initialization--
       --any other method if you have like I have --
         $scope.change = function (item) {
          -------- my implementation 
     };
     $scope.selected = function (item) {
         -------- my implementation
    };
//Actual click event should be handled in link function
function link($scope, element, attributes, ngModel) {
   --other methods if you have any--
element.bind('click', function(event) {
                $document.on("click", $scope.onClick);
                event.stopPropagation();
            });

            $scope.onClick = function (event) {
                $scope.opened = false;
                $scope.$apply(attributes.multiSelect);
                $document.off("click", $scope.onClick);
            };
         }

        return {
            restrict: 'E',
            controller: controller,
            link: link,
            require: "ngModel",
            templateUrl: 'your template file(e.g: filename.tpl.html)'
        };

Hope it helps

Upvotes: 0

Vaibhav Raut
Vaibhav Raut

Reputation: 472

i think this will solve your problem

post: function ($scope, element, attrs, controller) { 
  element.on("click", function(){
    console.log("in element Click event");
    $scope.onElementClick = true;
    $document.on("click", $scope.onClick);
  });

  $scope.onClick = function (event) {
    if($scope.onElementClick)
    {
      $scope.onElementClick = false;
      return;
    }
    $scope.$apply(attrs.clickAnywhereButHere)
    $document.off("click", $scope.onClick);
  };
}

Upvotes: 3

Related Questions