1

I am using a custom directive for multiSelect dropdown. I needed a custom tirggering of open and close the multiSelect list using a custom button.

Problem: I got $apply already in progress error

Solution: To solve this I wrapped my jQuery function in $timeout

$timeout(function () {
    $('button.dropdown-toggle').trigger('click');
});

However, now I could make custom click to directive and my multiSelect would open, but now if on 2nd click I want to close the select box, it flickers, and keeps open. ;(

Directive:

if (!parentFound) {
    $scope.$apply(function(){
        $scope.open = false;
    });
}

Can someone propose a solution so that my toggling of multiSelect dropdown works now (after using $timeout) instead of opening only in all clicks?

enter image description here

2 Answers 2

1

Only negate the $scope value:

$scope.$apply(function() {
  if($scope.open) { //only close when it is open
    $scope.open = !$scope.open;
  }
});

If you wish to close the dropdown when you click outside the select box you can use another custom directive, which listens on the window for click events. This will broadcast a new event which you can listen for:

myApp.directive('dropdownListener', function ($window, $rootScope) {
    return {
        restrict: 'A',

        link: function(scope, element, attr) {
          var w = angular.element($window);

          w.bind('click', function(){
            $rootScope.$broadcast('dropdown:close');
          });
        }
    }
});

This means you can modify the original action by include a listener dropdown:close event:

$scope.$on('dropdown:close', function (event, data) {
   $scope.$apply(function() {
      if($scope.open) { //only close when it is open
        $scope.open = !$scope.open;
      }
    });
});
Sign up to request clarification or add additional context in comments.

Comments

1

Remove it out of $scope.$apply as

if (!parentFound) { function(){ $scope.open = false; }; }

For this first needs to understand $scope.$apply()

AngularJs creates a "watch" internally for the all data-bindings created in view and call $scope.$digest() which in turns iterate through all watches and checks if any of the watched variables have changed. When you call $scope.$apply() it internally calls $scope.$digest() so data-binding gets refreshed.

Listener directives, such as ng-click, register a listener with the DOM. When the DOM listener fires, the directive executes the associated expression and updates the view using the $apply() method.

When an external event (such as a user action, timer or XHR) is received, the associated expression must be applied to the scope through the $apply() method so that all listeners are updated correctly (ref).

So in your case $scope.$apply() is already called on click event and so throwing an error.

Also would be usefult to read this

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.