angular-multi-select icon indicating copy to clipboard operation
angular-multi-select copied to clipboard

Another buttons click event fires before on-close

Open brentvee opened this issue 7 years ago • 4 comments

I'm experiencing a weird issue where I have a search button with a bound ng-click="search()". When opening the multi-select control, selecting some items, then immediately clicking my search button (so just clicking away from the multi-select, but directly on my search button), the search button's click event is firing before the on-close event of the multi-select. Is there something I should be doing differently? Thanks

brentvee avatar Jan 23 '18 06:01 brentvee

Did you find solution? Because i'm also experiencing this problem

th0mas86 avatar Apr 13 '18 05:04 th0mas86

My current workaround is to fire the on-close event manually during the search button's click event

brentvee avatar Apr 13 '18 05:04 brentvee

Working example: http://embed.plnkr.co/YOlzjtEXOseugxkyonWS/

th0mas86 avatar Apr 13 '18 05:04 th0mas86

@brentvee In my understanding that happens because it is using $timeout to fire the event, which eventually queued up the event and fire that event in next digest cycle. Check code here. Find detailed explanation and solution below.

Root cause of this could be because of two things.

  1. The way externalClickEvent(responsible for calling onClose event) listener has been registered on document, it calls onClose event on it. For your case, the way event propagation works is it calls button event first, and then call externalClickEvent(registered on document)
  2. $timeout wrapped around onClose method, will eventually queued up onClose method and call it on next digest after ng-click method got fire.

To fix the issue you can change the event bubbling order, to fire document event first and then the button event by replacing this line by below line

// true flat change the direction of event propagation / bubbling
document.addEventListener('click', $scope.externalClickListener, true); 

and change $timeout with $apply calling on immediate next line

$timeout( function() {
   $scope.onClose();
}, 0 );

to

 $scope.onClose();
 $scope.$apply();

Working Plunker

Note: Not sure about what would be implication of this solution.

pankajparkar avatar Jun 16 '18 17:06 pankajparkar