30

I found this question very useful for submitting a form when someone presses the "enter" key:

Javascript:

angular.module('yourModuleName').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': event});
                });

                event.preventDefault();
            }
        });
    };
});

HTML:

<div ng-app="" ng-controller="MainCtrl">
    <input type="text" ng-enter="doSomething()">    
</div>

What I would like to do know, is to set the field to blur when the "enter" key is pressed. What would doSomething() look like to blur the sender field?

I would like to leave the ngEnter directive as it is, since I would like to re-use it for other functions.

Update: I know I can create a whole directive just for blurring (that's how I have it now), but what I'd like to do is be able to do something like this:

<input type="text" ng-enter="this.blur()">

Or how do I pass the current element as a parameter?

<input type="text" ng-enter="doBlur(this)">
Community
  • 1
  • 1
coopersita
  • 5,011
  • 3
  • 27
  • 48
  • possible duplicate of [Angular js trigger blur event](http://stackoverflow.com/questions/23300329/angular-js-trigger-blur-event) – SoluableNonagon Dec 01 '14 at 18:58
  • Also, http://stackoverflow.com/questions/18389527/angularjs-submit-on-blur-and-blur-on-keypress – SoluableNonagon Dec 01 '14 at 18:58
  • @SoluableNonagon I updated my question. I know I can make a custom directive just for blurring, but I want to keep the directive generic. – coopersita Dec 01 '14 at 19:49
  • I think you will need a custom directive just for blurring. Don't know of a good way to do this except to pass an event to the doBlur function. Like so: http://stackoverflow.com/questions/12994710/in-angularjs-how-to-access-the-element-that-triggered-the-event but you will need something to pass $event – SoluableNonagon Dec 01 '14 at 20:20
  • I was afraid of that... Thanks for trying, though. – coopersita Dec 01 '14 at 20:28
  • Hi, if my answer or the other helped you could you select one? – SoluableNonagon Dec 12 '16 at 05:59

3 Answers3

33

After trying a bunch of things, this is seems not possible, as you would need to pass $event to get the target element, so separate directive seems to be the only way to go:

What we desire:

You cannot pass this because it refers to the scope, so you need to pass the event.

<input type="text" ng-enter="doBlur($event)">

Once you have the event, you can get the target from it.

$scope.doBlur = function($event){
    var target = $event.target;

    // do more here, like blur or other things
    target.blur();
}

But, you can only get pass event in a directive like ng-click ... kinda unsatisfactory. If we could pass $event outside directive, we could blur in that reusable way you requested.

SoluableNonagon
  • 11,541
  • 11
  • 53
  • 98
  • 2
    I hate to say this, but it seems jQuery would be easier to use in this case – SoluableNonagon Dec 01 '14 at 20:35
  • 1
    This solution worked with me only when I passed the event parameter as per this line of code: `scope.$eval(attrs.ngEnter, {'event': event});`. Thanks a lot. – tarekahf Sep 20 '16 at 21:49
  • Worked fine in Chrome, but in Firefox and Edge the focus was lost. To keep focus: `target.focus()` – Markus Pscheidt Apr 05 '17 at 13:36
  • @SoluableNonagon React has a more elegant approach than this too. You don't need jQuery. You just need a framework that is designed for the web, not for Java applications. – Daniel Viglione Mar 31 '20 at 16:40
6

for Angular 2+

<input ... (keydown.enter)='$event.target.blur()'>
  • This needs more upvotes since angular 2+ is presumably gaining over angularjs. – MrBoJangles Dec 13 '19 at 16:57
  • to solve Property 'blur' does not exist on type 'EventTarget' error, use add an ID to the input element, and call blur on that: – niio May 31 '22 at 10:39
4

SoluableNonagon was very close to it. You just have to use the right argument. The directive declared the event parameter as event not $event. You could change the directive to use $event just as ngClick does (Or you keep it and use it as ng-enter="doSomething(event)".

angular.module("app", [])
  .controller('MainController', MainController)
  .directive('myEnter', myEnter);

function MainController() {
  var vm = this;
  vm.text = '';
  vm.enter = function($event) {
    $event.target.blur();
    vm.result = vm.text;
    vm.text = '';
  }
}

myEnter.$inject = ['$parse'];

function myEnter($parse) {
  return {
    restrict: 'A',
    compile: function($element, attr) {
      var fn = $parse(attr.myEnter, null, true);
      return function(scope, element) {
        element.on("keydown keypress", function(event) {
          if (event.which === 13) {
            
            // This will pass event where the expression used $event
            fn(scope, { $event: event });
            scope.$apply();
            event.preventDefault();
          }
        });
      };
    }
  };
}
<script src="https://code.angularjs.org/1.4.8/angular.js"></script>

<div ng-app="app" ng-controller="MainController as view">
  <input my-enter="view.enter($event)" ng-model="view.text">
  <div ng-bind="view.result"></div>
</div>
Community
  • 1
  • 1
hansmaad
  • 18,417
  • 9
  • 53
  • 94