Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I simplify clicking the enter key with AngularJS?

Tags:

angularjs

I already have this code that I came up with:

In my outer controller:

    $scope.key = function ($event) {
        $scope.$broadcast('key', $event.keyCode)
    }

In my inner controller (I have more than one like this)

    $scope.$on('key', function (e, key) {
        if (key == 13) {
            if (ts.test.current) {
                var btn = null;
                if (ts.test.userTestId) {
                    btn = document.getElementById('viewQuestions');
                } else {
                    btn = document.getElementById('acquireTest');
                }
                $timeout(function () {
                    btn.focus();
                    btn.click();
                    window.setTimeout(function () {
                        btn.blur();
                    }, 500);
                })
            } 
        }
    });

Is there another way that I could simplify this using some features of AngularJS that I have not included here?

like image 417
Samantha J T Star Avatar asked Jul 22 '15 12:07

Samantha J T Star


2 Answers

Please check this gist, https://gist.github.com/EpokK/5884263

You can simply create a directive ng-enter and pass your action as paramater

app.directive('ngEnter', function() {
  return function(scope, element, attrs) {
    element.bind("keydown keypress", function(event) {
      if(event.which === 13) {
        scope.$apply(function(){
          scope.$eval(attrs.ngEnter);
        });
        event.preventDefault();
      }
    });
  };
});

HTML

<input ng-enter="myControllerFunction()" />

You may change the name ng-enter to something different, because ng-** is a reserved by Angular core team.

Also I see that your controller is dealing with DOM, and you should not. Move those logic to other directive or to HTML, and keep your controller lean.

if (ts.test.userTestId) {
  btn = document.getElementById('viewQuestions'); //NOT in controller
} else {
  btn = document.getElementById('acquireTest');   //NOT in controller
}
$timeout(function () {  
    btn.focus();      //NOT in controller
    btn.click();      //NOT in controller
    window.setTimeout(function () { // $timeout in $timeout, questionable
        btn.blur();  //NOT in controller
    }, 500);
})
like image 90
allenhwkim Avatar answered Oct 28 '22 09:10

allenhwkim


What i've done in the past is a directive which just listens for enter key inputs and then executes a function that is provided to it similar to an ng-click. This makes the logic stay in the controller, and will allow for reuse across multiple elements.

//directive
angular.module('yourModule').directive('enterHandler', [function () {
    return{
        restrict:'A',
        link: function (scope, element, attrs) {
            element.bind("keydown keypress", function (event) {
                var key = event.which ? event.which : event.keyCode;
                if (key === 13) {
                    scope.$apply(function () {
                        scope.$eval(attrs.enterHandler);
                    });
                    event.preventDefault();
                }
            });
        }
    }
}]);

then your controller becomes

 $scope.eventHandler = function(){
     if (ts.test.current) {
            var btn = ts.test.userTestId 
                      ? document.getElementById('viewQuestions')  
                      : document.getElementById('acquireTest');
            $timeout(function () {
                btn.focus();
                btn.click();
                window.setTimeout(function () {
                    btn.blur();
                }, 500);
            })
        }
    }

and your markup can then be

<div enter-handler="eventHandler()" ></div>
like image 20
mikeswright49 Avatar answered Oct 28 '22 09:10

mikeswright49