简体   繁体   中英

Triggering custom jquery click on Angular Custom Directive

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?

在此处输入图片说明

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

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;
      }
    });
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM