369

In this particular case, what options do I have to make these inputs call a function when I press Enter?

Html:

<form>
    <input type="text" ng-model="name" <!-- Press ENTER and call myFunc --> />
    <br />
    <input type="text" ng-model="email" <!-- Press ENTER and call myFunc --> />
</form>
// Controller //
.controller('mycontroller', ['$scope',function($scope) {
    $scope.name = '';
    $scope.email = '';
    // Function to be called when pressing ENTER
    $scope.myFunc = function() {
       alert('Submitted');
    };
}])
General Grievance
  • 4,555
  • 31
  • 31
  • 45
ali
  • 10,927
  • 20
  • 89
  • 138

13 Answers13

522

Angular supports this out of the box. Have you tried ngSubmit on your form element?

<form ng-submit="myFunc()" ng-controller="mycontroller">
   <input type="text" ng-model="name" />
    <br />
    <input type="text" ng-model="email" />
</form>

EDIT: Per the comment regarding the submit button, see Submitting a form by pressing enter without a submit button which gives the solution of:

<input type="submit" style="position: absolute; left: -9999px; width: 1px; height: 1px;"/>

If you don't like the hidden submit button solution, you'll need to bind a controller function to the Enter keypress or keyup event. This normally requires a custom directive, but the AngularUI library has a nice keypress solution set up already. See http://angular-ui.github.com/

After adding the angularUI lib, your code would be something like:

<form ui-keypress="{13:'myFunc($event)'}">
  ... input fields ...
</form>

or you can bind the enter keypress to each individual field.

Also, see this SO questions for creating a simple keypres directive: How can I detect onKeyUp in AngularJS?

EDIT (2014-08-28): At the time this answer was written, ng-keypress/ng-keyup/ng-keydown did not exist as native directives in AngularJS. In the comments below @darlan-alves has a pretty good solution with:

<input ng-keyup="$event.keyCode == 13 && myFunc()"... />

Community
  • 1
  • 1
eterps
  • 14,198
  • 4
  • 35
  • 46
  • 9
    It only works if I have a submit button inside the form, too. – ali Mar 14 '13 at 19:16
  • I'll go with the custom directive, I can't use angular-ui. Thanks – ali Mar 14 '13 at 19:45
  • What about ng-change? – CMCDragonkai Aug 11 '13 at 14:55
  • The downside to this is ng-submit automatically checks form validity. ui-keypress won't AFAICT. – Chris Nicola Nov 19 '13 at 00:16
  • 3
    Also note that this HAS to be a
    it doesn't seem to work on which is what I tend to use.
    – John Culviner Jan 15 '14 at 17:57
  • So basically ng-submit only works when there's a submit button inside the form? Why not clone the ng-submit code, but just remove the part where it requires a submit button, and keep all the validation code. – CMCDragonkai Mar 08 '14 at 18:20
  • 1
    Just leaving a note: If you've ended up here and submit buttons don't work for you, you could be using a bad name for your submit function. I was foolishly using `ng-submit="join()"` for a registration controller that had `$scope.join = function() {...}` and changing that function name to `foo()` got enter-button submission working again. – tester Jun 23 '14 at 19:04
  • What's different between ui-keypress and the built-in ng-keypress? – user4815162342 Jun 25 '14 at 21:17
  • 1
    At the time this answer was written, ng-keypress/ng-keyup did not exist in Angular – eterps Aug 29 '14 at 19:06
  • 70
    `ng-keyup="$event.keyCode == 13 && myFunc()"` Really awesome :) – Honchar Denys Jun 19 '15 at 13:36
  • 1
    Just in case if someone is ignorant. Keep in mind that input type="button" will not trigger form submit. It needs to be input type="submit" button – sree Feb 15 '16 at 03:41
  • ... late to the party, but a hidden input with name submit `` will do the same trick as an actual submit button in terms of making the enter keypress submit a form, which I find elegant enough, compared to hiding the real one away from the screen. I would replace that in this post, but I don't want to put words in @eterps posts. I also find a hidden input more elegant than the keyup hack. – Félix Adriyel Gagnon-Grenier Jun 12 '17 at 20:31
  • ng-keyup="$event.keyCode == 13 && myFunc()" this dose not work in Firefox – Mayur Randive Jun 21 '17 at 09:00
  • At least as of Firefox 54.0.1 (64-bit) on Mac OS X the ng-keyup answer works. – Alison S Jul 28 '17 at 17:23
289

If you want to call function without form you can use my ngEnter directive:

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>

I submit others awesome directives on my twitter and my gist account.

ruhanbidart
  • 4,564
  • 1
  • 26
  • 13
EpokK
  • 38,062
  • 9
  • 61
  • 69
  • 2
    Is there a clever way to get this to trigger any time they hit enter while on your page? – Derek Adair Oct 16 '13 at 19:04
  • 1
    @EpokK I wanna disable the enter key for the entire form, how can I do that? (I want to avoid form submission with enter) – Antonio Max Oct 23 '13 at 22:52
  • @AntonioMax You could just have an extra flag within the directive that checks whether you want to person to be able to submit or not – NotSimon Oct 27 '13 at 12:41
  • 48
    very nice, but as per AngularJs' reccomendation, you shouldn't create directives, services, or filters that are prefixed with ng-, in case an official release later uses the same name. – Neil S Nov 11 '13 at 22:57
  • 5
    Great solution. I just changed the name to keyBind and this line "if(event.which === 13) {" to this "if(event.which === Number(attrs.key)) {" And then my input to "" so that I could re-use it for different key events. – Brian F Feb 06 '14 at 05:48
  • @Derek Adair: I'm quite new to angular directives, but I should try to use, instead of `element.bind(...`, `window.bind(...`... – MarcoS May 30 '14 at 10:52
  • A very similar answer is posted on this question: [How to use a keypress event in angularjs](http://stackoverflow.com/a/17472118/320399) – blong Jun 27 '14 at 18:51
  • 4
    IMPORTANT: Adding both the `keydown` and `keypress` events without a comma to delimit them means both may fire simultaneously. This is likely to spawn $rootScope:inprog errors. Adding a comma between them creates a disjunctive, and ensures only only $digest cycle occurs. Couldn't apply the edit since it's only a single character. – Ryan Miller Jul 11 '14 at 21:56
  • this doesn't capture the done event on iOS, I ended up listening to the blur event as well – Paul Wand Dec 29 '14 at 05:29
  • @BrianF - great solution. Thanks. You also have to change attrs.ngEnter to attrs.keyBind in the scope.$eval(...) function. – dustin.schultz Mar 13 '15 at 19:07
  • Maybe this is a very easy question but, where do you put the doSomething() method? – napstercake May 31 '15 at 23:29
  • @RicardoGonzales in your controller. – EpokK Jun 17 '15 at 01:40
  • Don't you need to take care of unbinding event on `unlink` or something? – Augustin Riedinger Aug 19 '15 at 11:56
  • This is perfect for when you have a simple input that isn't part of a form! I agree with @NeilS on not prefixing it with 'ng' though. – AForsberg Mar 23 '18 at 14:06
202

If you only have one input you can use the form tag.

<form ng-submit="myFunc()" ...>

If you have more than one input, or don't want to use the form tag, or want to attach the enter-key functionality to a specific field, you can inline it to a specific input as follows:

<input ng-keyup="$event.keyCode == 13 && myFunc()" ...>
Ben Cull
  • 9,434
  • 7
  • 43
  • 38
M M
  • 2,249
  • 1
  • 15
  • 6
  • 3
    This is a clever way of doing this without even having to write your own directive – Charlie Martin May 02 '14 at 22:11
  • 62
    Even shorter: – Darlan Alves Jun 11 '14 at 20:28
  • Works great, I used the ng-keyup directive, but I have one big issue with it, if I only have one text field, he submits the complete form (postback) but I don't want that. I tried already ng-keyup="$event.keyCode == 13 && onTextBoxKeyUp($event)" and in the function "event.preventDefault();", but did not help ;( – SharpNoiZy Sep 10 '14 at 10:45
  • this is shorter but keeping DRY approach in my mind i would still create directive and use it with directive. – Atul Chaudhary Aug 19 '15 at 23:28
  • This may be problematic depending upon the context - I have a form in which I have two buttons, (wizard like interface), with 'back' and 'next' button, default behaviour on clicking 'enter' key is back button. Now, when using above code, the back button get's CLICKED FIRST, and then myFunction() code is called (which in turns, get's to next part of wizard) So, my wizard goes BACK for a while, and then it goes forward. @EpokK's solution works perfect for me. – Vishwajeet Vatharkar Sep 09 '15 at 19:51
34

I wanted something a little more extensible/semantic than the given answers so I wrote a directive that takes a javascript object in a similar way to the built-in ngClass:

HTML

<input key-bind="{ enter: 'go()', esc: 'clear()' }" type="text"></input>

The values of the object are evaluated in the context of the directive's scope - ensure they are encased in single quotes otherwise all of the functions will be executed when the directive is loaded(!)

So for example: esc : 'clear()' instead of esc : clear()

Javascript

myModule
    .constant('keyCodes', {
        esc: 27,
        space: 32,
        enter: 13,
        tab: 9,
        backspace: 8,
        shift: 16,
        ctrl: 17,
        alt: 18,
        capslock: 20,
        numlock: 144
    })
    .directive('keyBind', ['keyCodes', function (keyCodes) {
        function map(obj) {
            var mapped = {};
            for (var key in obj) {
                var action = obj[key];
                if (keyCodes.hasOwnProperty(key)) {
                    mapped[keyCodes[key]] = action;
                }
            }
            return mapped;
        }
        
        return function (scope, element, attrs) {
            var bindings = map(scope.$eval(attrs.keyBind));
            element.bind("keydown keypress", function (event) {
                if (bindings.hasOwnProperty(event.which)) {
                    scope.$apply(function() {
                         scope.$eval(bindings[event.which]);
                    });
                }
            });
        };
    }]);
Community
  • 1
  • 1
Alex
  • 7,639
  • 3
  • 45
  • 58
  • I get a angluarjs HTML parse error when i try to add a string variable in the function. key-bind="{ enter: 'vm.doTheThing('myVar')' }" – MaylorTaylor Jun 22 '18 at 15:05
  • Also noticed that if i use function with an Object as a variable, the function happens more than once. The code below remove 2+ items when i run this. key-bind="{ enter: 'vm.removeItem(item)' }" – MaylorTaylor Jun 22 '18 at 15:39
  • 1
    @MaylorTaylor for the first issue, use different types of quotes i.e. `'vm.doTheThing("myVar")'` – Alex Jun 25 '18 at 10:09
28

Another approach would be using ng-keypress ,

<input type="text" ng-model="data" ng-keypress="($event.charCode==13)? myfunc() : return"> 

Submit an input on pressing Enter with AngularJS - jsfiddle

Partha Roy
  • 1,575
  • 15
  • 16
14

Very good, clean and simple directive with shift + enter support:

app.directive('enterSubmit', function () {
    return {
        restrict: 'A',
        link: function (scope, elem, attrs) {
            elem.bind('keydown', function(event) {
                 var code = event.keyCode || event.which;
                 if (code === 13) {
                       if (!event.shiftKey) {
                            event.preventDefault();
                            scope.$apply(attrs.enterSubmit);
                       }
                 }
            });
        }
    }
});
Vlatko
  • 1,385
  • 1
  • 18
  • 35
5

If you want data validation too

<!-- form -->
<form name="loginForm">
...
  <input type="email" ng-keyup="$loginForm.$valid && $event.keyCode == 13 && signIn()" ng-model="email"... />
  <input type="password" ng-keyup="$loginForm.$valid && $event.keyCode == 13 && signIn()" ng-model="password"... />
</form>

The important addition here is $loginForm.$valid which will validate the form before executing function. You will have to add other attributes for validation which is beyond the scope of this question.

Good Luck.

Aakash
  • 21,375
  • 7
  • 100
  • 81
2

Just wanted to point out that in the case of having a hidden submit button, you can just use the ngShow directive and set it to false like so:

HTML

<form ng-submit="myFunc()">
    <input type="text" name="username">
    <input type="submit" value="submit" ng-show="false">
</form>
landesko
  • 373
  • 1
  • 5
  • 16
  • 1
    +1 `` is even shorter. No need to set the value of an invisible button. – musa Jul 04 '17 at 08:15
  • It was my understanding that in order to trigger the ng-submit directive, an input of `type="submit"` ... I suppose value could be ignored but I believe the former is necessary. – landesko Jul 05 '17 at 14:23
1

Use ng-submit and just wrap both inputs in separate form tags:

<div ng-controller="mycontroller">

  <form ng-submit="myFunc()">
    <input type="text" ng-model="name" <!-- Press ENTER and call myFunc --> />
  </form>

  <br />

  <form ng-submit="myFunc()">
    <input type="text" ng-model="email" <!-- Press ENTER and call myFunc --> />
  </form>

</div>

Wrapping each input field in its own form tag allows ENTER to invoke submit on either form. If you use one form tag for both, you will have to include a submit button.

Myclamm
  • 57
  • 1
  • 6
0

Will be slightly neater using a CSS class instead of repeating inline styles.

CSS

input[type=submit] {
    position: absolute;
    left: -9999px;
}

HTML

<form ng-submit="myFunc()">
    <input type="text" ng-model="name" />
    <br />
    <input type="text" ng-model="email" />
    <input type="submit" />
</form>
guya
  • 5,067
  • 1
  • 35
  • 28
0

FWIW - Here's a directive I've used for a basic confirm/alert bootstrap modal, without the need for a <form>

(just switch out the jQuery click action for whatever you like, and add data-easy-dismiss to your modal tag)

app.directive('easyDismiss', function() {
    return {
        restrict: 'A',
        link: function ($scope, $element) {

            var clickSubmit = function (e) {
                if (e.which == 13) {
                    $element.find('[type="submit"]').click();
                }
            };

            $element.on('show.bs.modal', function() {
                $(document).on('keypress', clickSubmit);
            });

            $element.on('hide.bs.modal', function() {
                $(document).off('keypress', clickSubmit);
            });
        }
    };
});
0

you can simply bind @Hostlistener with the component, and rest will take care by it. It won't need binding of any method from its HTML template.

@HostListener('keydown',['$event'])
onkeydown(event:keyboardEvent){
  if(event.key == 'Enter'){
           // TODO do something here
           // form.submit() OR API hit for any http method
  }
}

The above code should work with Angular 1+ version

Ankit
  • 292
  • 1
  • 6
  • 17
0

I focused to below row input in the table

<input ng-keydown="$event.keyCode == 13 && onPressEnter($event)" id="input_0" type="text" >

    $scope.onPressEnter = function (event) {
    let inputId = event.target.id;
    let splited = inputId.split('_');
    let newInputId = 'input' + '_' + ((+splited[1]) + 1);
    if (document.getElementById(newInputId))
        document.getElementById(newInputId).focus();
   // else submit form
}
M Komaei
  • 7,006
  • 2
  • 28
  • 34