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.