Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

triggerHandler causing Error: [$rootScope:inprog] $apply already in progress error - AngularJS

I am trying to trigger the click of a button when a key is pressed. I'm doing this using the triggerHandler function, but this is causing the error above. I'm thinking I must have created some kind of circular reference/loop, but I can't see where.

This is my HTML:

<button id="demoBtn1" hot-key-button hot-key="hotKeys.primaryTest" class="po-btn primary-btn" type="submit" ng-click="btnFunction()"></button>

Here's my controller:

.controller('BtnCtrl', function ($scope) {
    $scope.checkKeyPress = function ($event, hotKeyObj) {
        for(var key in hotKeyObj) {
            if($event.keyCode == hotKeyObj[key].keyCode) {
                var id = hotKeyObj[key].btnId;
                hotKeyObj[key].funcTriggered(id);
            }
        }
    }
    $scope.clickFunction = function(id) {
        var currentButton = angular.element(document.getElementById(id));
        currentButton.triggerHandler("click");
    }
    $scope.btnFunction = function() {
        console.log("clickFunction1 has been triggered");
    }

    $scope.hotKeys = {
        'primaryTest': {
            keyCode: 49,
            keyShortcut: "1",
            label: "Button",
            btnId: 'demoBtn1',
            funcTriggered: $scope.clickFunction
        },
        // more objects here
        }
    }
})

And my directive is here:

.directive("hotKeyButton", function() {
    return {
        controller: 'BtnCtrl',
        scope: {
            hotKey: '='
        },
        transclude: true,
        template: "<div class='key-shortcut'>{{hotKey.keyShortcut}}</div><div class='hotkey-label'>{{hotKey.label}}</div>"
    };
})

It's a bit of a work in progress, so I suspect there might be small errors in places, but I'm primarily interested in the logic running from the keypress to btnFunction being triggered. The error fires on the currentButton.triggerHandler("click") line.

Can anyone see what I've done? Thanks.

like image 487
MDalt Avatar asked Dec 09 '22 01:12

MDalt


1 Answers

Since you have a problem with $apply in progress - you can just wrap your triggerHandler call into $timeout wrapper - just to make everything you need in another $digest-cycle, like this:

$scope.clickFunction = function(id) {
    var currentButton = angular.element(document.getElementById(id));
    $timeout(function () {
      currentButton.triggerHandler("click");
    });
}

After this everything will work OK.

  • Also don't forget to $inject $timeout service into your BtnCtrl.
  • Also i'm not sure you need to define controller property for your directive, but it's not a main case.

Demo: http://plnkr.co/edit/vO8MKAQ4397uqqcAFN1D?p=preview

like image 113
ababashka Avatar answered Mar 08 '23 23:03

ababashka