61

How can I prevent the enter key from submitting the form in angular?

Is there a way to catch the 13 key and disable it or set the form as invalid unless submitting from a button with ID of x?

Thanks

beaudetious
  • 2,354
  • 3
  • 36
  • 60
Antonio Max
  • 8,627
  • 6
  • 43
  • 42

15 Answers15

111

Since you have ng-click anyways, you could also use <button type="button">, even inside the form tag. The default behaviour of the button element is type="submit", which is what you want to prevent. So, no javascript needed at all!

Michael Klöpzig
  • 1,235
  • 1
  • 8
  • 7
  • 1
    This will only work if there's more than one non type hidden input, as far as I could tell. – João Josézinho Mar 22 '15 at 16:29
  • 3
    To mention, i think this will not trigger the front end validations if you left (you had ng-reguired/required etc and did no use novalidate directive on the form) – Vlad Oct 06 '15 at 12:10
  • 8
    this solution only works for buttons, but if you press "enter" in input-type-text field - you still have form sent. – Yevgeniy Afanasyev Dec 18 '15 at 01:59
  • 6
    PLEASE NOTE: buttons without a type="..." declaration are "submit" by default! So make sure you always use type="button". – ESP32 Jan 28 '16 at 10:03
  • 3
    @YevgeniyAfanasyev the "enter" in input-type-text field will trigger the submit button inside the form, so if you only have ` – Dinei Jul 20 '17 at 14:52
  • @DineiRockenbach, but if you change types on every button of your form to "button" how would you submit it when time comes? Do you suggest dynamically change type of one button? – Yevgeniy Afanasyev Jul 26 '17 at 00:27
  • 1
    @YevgeniyAfanasyev No, dynamically changing input/button types is bad idea. One could put the submit code on button's onclick event, but Michael's solution seems better. I just noted in my previous comment that the solution provided by Michael should work even if you press "enter" in input type="text". – Dinei Jul 26 '17 at 16:17
  • @DineiRockenbach, sorry, with your last message we are in the loop. I have my doubts about Michael's solution and I described it in my first comment. Now you are sticking to the same idea without providing thoughts about my doubts. – Yevgeniy Afanasyev Jul 28 '17 at 00:09
25

Other users have already written that [button type="submit"] will cause this trouble. PLEASE NOTE: buttons WITHOUT any type="..." declaration are "submit" by default! So make sure you always use type="button".

ESP32
  • 8,089
  • 2
  • 40
  • 61
  • `type="search` and `type="text"` do attempt to submit on enter (firefox 45), changed from `form` to plain `div` to avoid it – svarog Mar 10 '16 at 14:19
12

After a couple hours, this weird code was the only thing that worked.

I'm waiting for better answers, won't accept this monster:

app.directive('onKeyup', function() {
    return function(scope, elm, attrs) {
      var allowedKeys = scope.$eval(attrs.keys);
      elm.bind('keydown', function(evt) {           
        angular.forEach(allowedKeys, function(key) {
          if (key == evt.which) {
             evt.preventDefault(); // Doesn't work at all
             window.stop(); // Works in all browsers but IE    
             document.execCommand("Stop"); // Works in IE
             return false; // Don't even know why it's here. Does nothing.                     
          }
        });
      });
    };
});

and trigger it by using this on all form inputs:

<input on-keyup="bla" keys="[13]" .... />

For now, whenever the user press the enter key, the window try to submit, then fail to do so, not so silently. Ugly but it works.

Edit: keydown is a little better than keyup for the element bind, now enter key fails silently-ish

MrBoJangles
  • 12,127
  • 17
  • 61
  • 79
Antonio Max
  • 8,627
  • 6
  • 43
  • 42
12

so simple, doesn't need to do anything. just add this to your form tag if you are using angular +2

<form (keydown.enter)="$event.preventDefault()" ...>
pouyada
  • 341
  • 3
  • 15
11

If you are attempting to prevent the form from being submitted on just a single element, you can add the following ng-keypress handler (this is for Angular 1.x):

<input type="text" name="myField" ng-keypress="keyPressHandler($event)"/>

With the following implementation for keyPressHandler:

$scope.keyPressHandler = function(e) {
    if (e.keyCode === 13) {
        e.preventDefault();
        e.stopPropagation();

        // Perform your custom logic here if any
    }
}
Kenny DiFiore
  • 151
  • 1
  • 6
  • This worked for my situation. If you are using the alternate vm. instead of $scope in AngularJS (1.x) you will likely need to add that to your ng-keypress directive inside the input, like this: ng-keypress="vm.keyPressHandler($event)" so it will work correctly. Thanks! – Ryan Apr 24 '19 at 19:05
8

I had a similar problem, I ended up taking the button out of the form. Seeing as I use ng-click and everything is binded with ng-model it doesn't really matter if it's inside the form or not.

I realise this is bad practice but it sure as hell beats writing a custom directive to intercept keystrokes.

McMeep
  • 688
  • 2
  • 8
  • 13
6

Check this:

if a form has 2+ input fields and no buttons or input[type=submit] then hitting enter doesn't trigger submit

Thus if your form has 2+ input fields, you could use something like <span ng-click="submit()">Sumbit</span> to prevent key-trigger of enter key in those input fields.

okm
  • 23,575
  • 5
  • 83
  • 90
6

I came across this issue. Yes, you would need to remove all type='submit' from your page, and make sure any other buttons have type="button" but then the challenge is still being able to use normal validation submission.

I created a directive that triggers form submission + form states for validation. Replacing:

<button type="submit">

with

<button submit-button type="button">

Directive:

export default /*@ngInject*/ function submitButton($log) {
return ({
    require: '^form',
    link: link,
    restrict: 'A'
});

function link(scope, element, attributes, formCtrl) {

    element.on('click', clickHandler);

    function clickHandler() {
        formCtrl.$setDirty(true);
        formCtrl.$setSubmitted(true);
        angular.element(element[0].form).triggerHandler('submit');
        $log.info('Form Submitted');
    }

}

You can still hit ENTER to submit when focused on your submit-button, better for UX and Accessibility I think.

Jamie Kemp
  • 101
  • 1
  • 4
2

The easiest solution to this I found is to use input type as button instead of submit and bind the form submit function with ng-click and not using the ng-submit in the form tag.

I hope this helps.

Mohit Aneja
  • 428
  • 4
  • 11
2

This is my weird but quick and simple solution without any directives.

HTML:

  <form ng-submit='submitForm()'>
    <input type='text'>
    <button type='submit' ng-mousedown='doSubmit=true'>submit</button>
  </form>

Controller:

  $scope.submitForm = function() {
    if (!$scope.doSubmit) {
        return;
    }
    $scope.doSubmit = false;
    console.log('execute some actions');
  }
1

You can catch the default form submit in your controller using ng-submit on the form tag and it will prevent a submit:

http://docs.angularjs.org/api/ng.directive:ngSubmit

alternatively, if you really wanted to catch the key events, there are also directives for that which pass an event you can call stop:

http://docs.angularjs.org/api/ng.directive:ngKeyup

  • ng-keyup only works on 1.1.5+ and I'm stuck with 1.0.7. I have no idea on how to catch the enter key using the ngsubmit thing. – Antonio Max Oct 23 '13 at 19:09
  • your link is dead. the link does not describe how to prevent it. you should place the code necessary to answer the question here. – activedecay Jun 17 '21 at 21:51
1
angular.element(document).ready(function () {
    angular.element(window).keydown(function () {
        if(event.keyCode == 13) {
                  event.preventDefault();
                  return false;
        }
    });
});

Try with this in angularjs controller

Farhad
  • 4,119
  • 8
  • 43
  • 66
0

A form is submitted when the enter key is clicked while a control within the form has focus. If you register a listener using ng-submit you can intercept this and use prevent defaults to stop the default process (i.e. submitting the form). Have a look at th

0

The following should work . . . i.e., the form is only submitted on button click, and not on hitting Enter in the Input boxes. (This definitely works for reactive forms. I didn't test it for template forms).

<form #form [formGroup]="form" METHOD="GET" action="http://localhost:3000/test">
  <input placeholder="Enter"/>
  <input placeholder="The Dragon"/>
  <button type="button" (click)="form.submit()">Submit</button>
</form>

Of course, remember all the imports and declarations:

app.module.ts

import { FormsModule, ReactiveFormsModule } from '@angular/forms';

@NgModule({
  imports: [
. . .
    FormsModule,
    ReactiveFormsModule

  ]
. . . 
})
export class AppModule { }

test.component.ts

import { FormGroup, FormControl } from '@angular/forms';

@Component({
  selector: 'app-test',
  templateUrl: './test.component.html',
  styleUrls: ['./test.component.scss']
})
export class TestComponent {
  form: FormGroup = new FormGroup({});
  constructor() { }

}

Crowdpleasr
  • 3,574
  • 4
  • 21
  • 37
-1

Try setting a variable when you click the submit button and checking that it has been set in the form submit.

$scope.click = function () {
    $scope.clicked = true;
    $scope.submit();
};

$scope.submit = function () {
    if ($scope.clicked) {
        ... submit
    } else {
        ... prevent defaults
    }
     $scope.clicked = false;
};

See jsfiddle

tocallaghan
  • 8,432
  • 1
  • 28
  • 23
  • this doesn't cover form submission from an enter key press – andygoestohollywood Jan 28 '14 at 00:12
  • 1
    A form is submitted when the enter key is clicked while a control within the form has focus. If you register a listener using ng-submit you can intercept this and use prevent defaults to stop the default process (i.e. submitting the form). Have a look at the jsfiddle, the form is submitted if the button is clicked but blocked if the enter key is clicked (though you would have to replace my examples with return 0 or preventDefault) – tocallaghan Jan 28 '14 at 04:12
  • Right... The bit you don't cover is the essential part the guy was asking – andygoestohollywood Jan 28 '14 at 11:01
  • Not sure what you mean, is it about prevent defaults? That's fairly trivial and actually in the answer. Either way, maybe you should consider asking a separate question – tocallaghan Feb 04 '14 at 03:11