angularjsonclickjquery-triggerhandler

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.


Solution

  • 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.

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