Senden Sie das Formular, indem Sie mit AngularJS die Eingabetaste drücken

364

Welche Optionen muss ich in diesem speziellen Fall haben, damit diese Eingaben eine Funktion aufrufen, wenn ich die Eingabetaste drücke?

// HTML view //
<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');
    };
}])
ali
quelle

Antworten:

518

Angular unterstützt dies sofort. Haben Sie ngSubmit für Ihr Formularelement ausprobiert ?

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

BEARBEITEN: Gemäß dem Kommentar zur Schaltfläche " Senden" finden Sie unter Senden eines Formulars durch Drücken der Eingabetaste ohne Schaltfläche "Senden" die folgende Lösung:

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

Wenn Ihnen die versteckte Submit-Button-Lösung nicht gefällt, müssen Sie eine Controller-Funktion an das Enter-Tastendruck- oder Keyup-Ereignis binden. Dies erfordert normalerweise eine benutzerdefinierte Direktive, aber in der AngularUI-Bibliothek ist bereits eine nette Tastendrucklösung eingerichtet. Siehe http://angular-ui.github.com/

Nach dem Hinzufügen der angleUI lib wäre Ihr Code ungefähr so:

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

oder Sie können die Eingabetaste an jedes einzelne Feld binden.

Weitere Informationen zum Erstellen einer einfachen keypres-Direktive finden Sie in den folgenden SO-Fragen: Wie kann ich onKeyUp in AngularJS erkennen?

EDIT (28.08.2014): Zum Zeitpunkt der Erstellung dieser Antwort existierte ng-keypress / ng-keyup / ng-keydown nicht als native Direktiven in AngularJS. In den Kommentaren unten hat @ darlan-alves eine ziemlich gute Lösung mit:

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

eterps
quelle
9
Es funktioniert nur, wenn ich auch eine Senden-Schaltfläche im Formular habe.
Ali
3
Beachten Sie auch, dass dies ein <Formular> sein muss. Es scheint nicht mit <someElement ng-form = "" ...> zu funktionieren, was ich normalerweise benutze.
John Culviner
1
Nur eine Notiz hinterlassen: Wenn Sie hier gelandet sind und die Senden-Schaltflächen für Sie nicht funktionieren, verwenden Sie möglicherweise einen schlechten Namen für Ihre Senden-Funktion. Ich habe dummerweise ng-submit="join()"einen Registrierungs-Controller verwendet, der $scope.join = function() {...}diesen Funktionsnamen hatte, und ihn geändert, damit foo()die Eingabe der Eingabetaste wieder funktioniert.
Tester
1
Zu dem Zeitpunkt, als diese Antwort geschrieben wurde, existierte ng-keypress / ng-keyup in Angular
eterps
69
ng-keyup="$event.keyCode == 13 && myFunc()"Wirklich großartig :)
Gonchar Denys
286

Wenn Sie eine Funktion ohne Formular aufrufen möchten, können Sie meine ngEnter-Direktive verwenden:

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>

Ich reiche andere großartige Anweisungen ein reiche meinem Twitter und meinem Hauptkonto ein .

EpokK
quelle
2
Gibt es eine clevere Möglichkeit, dies auszulösen, wenn sie auf Ihrer Seite die Eingabetaste drücken?
Derek Adair
1
@EpokK Ich möchte die Eingabetaste für das gesamte Formular deaktivieren. Wie kann ich das tun? (Ich möchte das Senden von Formularen mit Enter vermeiden)
Antonio Max
47
Sehr schön, aber gemäß der Empfehlung von AngularJs sollten Sie keine Anweisungen, Dienste oder Filter erstellen, denen ng- vorangestellt ist, falls eine offizielle Version später denselben Namen verwendet.
Neil S
5
Tolle Lösung. Ich habe gerade den Namen in keyBind geändert und diese Zeile "if (event.which === 13) {" in this "if (event.which === Number (attrs.key)) {" Und dann meine Eingabe in "< input type = "text" bind-key = "doSomething ()" key = "13"> ", damit ich es für verschiedene Schlüsselereignisse wiederverwenden kann.
Brian F
4
WICHTIG: Wenn Sie sowohl die keydownals auch die keypressEreignisse ohne Komma hinzufügen, um sie abzugrenzen, können beide gleichzeitig ausgelöst werden. Dies führt wahrscheinlich zu $ ​​rootScope: Inprog-Fehlern. Das Hinzufügen eines Kommas zwischen ihnen erzeugt einen Disjunktiv und stellt sicher, dass nur der $ Digest-Zyklus auftritt. Die Bearbeitung konnte nicht angewendet werden, da es sich nur um ein einzelnes Zeichen handelt.
Ryan Miller
197

Wenn Sie nur eine Eingabe haben, können Sie das Formular-Tag verwenden.

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

Wenn Sie mehr als eine Eingabe haben oder das Formular-Tag nicht verwenden oder die Eingabetaste an ein bestimmtes Feld anhängen möchten, können Sie es wie folgt an eine bestimmte Eingabe anhängen:

<input ng-keyup="$event.keyCode == 13 && myFunc()" ...>
MM
quelle
2
Dies ist eine clevere Möglichkeit, dies zu tun, ohne Ihre eigene Anweisung schreiben zu müssen
Charlie Martin
59
Noch kürzer: <input ng-keyup = "$ event.keyCode == 13 && myFunc ()" ... />
Darlan Alves
Funktioniert hervorragend, ich habe die ng-keyup-Direktive verwendet, aber ich habe ein großes Problem damit. Wenn ich nur ein Textfeld habe, sendet er das vollständige Formular (Postback), aber das möchte ich nicht. Ich habe bereits versucht, ng-keyup = "$ event.keyCode == 13 && onTextBoxKeyUp ($ event)" und in der Funktion "event.preventDefault ();", aber nicht geholfen; (
SharpNoiZy
Dies ist kürzer, aber wenn ich den DRY-Ansatz im Kopf habe, würde ich trotzdem eine Direktive erstellen und sie mit der Direktive verwenden.
Atul Chaudhary
Dies kann je nach Kontext problematisch sein. Ich habe ein Formular, in dem ich zwei Schaltflächen (zaubererähnliche Oberfläche) mit den Schaltflächen "Zurück" und "Weiter" habe. Das Standardverhalten beim Klicken auf die Eingabetaste ist die Schaltfläche "Zurück". Wenn Sie den obigen Code verwenden, wird die Zurück-Schaltfläche zuerst geklickt, und dann wird der myFunction () -Code aufgerufen (der wiederum zum nächsten Teil des Assistenten gelangt). Mein Assistent geht also für eine Weile ZURÜCK und dann vorwärts. Die Lösung von @ EpokK funktioniert perfekt für mich.
Vishwajeet Vatharkar
33

Ich wollte etwas, das etwas erweiterbarer / semantischer ist als die gegebenen Antworten, also schrieb ich eine Direktive, die ein Javascript-Objekt ähnlich wie das eingebaute verwendet ngClass :

HTML

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

Die Werte des Objekts werden im Kontext des Gültigkeitsbereichs der Direktive ausgewertet. Stellen Sie sicher, dass sie in einfache Anführungszeichen gesetzt sind. Andernfalls werden alle Funktionen ausgeführt, wenn die Direktive geladen wird (!).

Also zum Beispiel: esc : 'clear()'stattesc : 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]);
                    });
                }
            });
        };
    }]);
AlexFoxGill
quelle
Ich erhalte einen angluarjs HTML-Analysefehler, wenn ich versuche, der Funktion eine Zeichenfolgenvariable hinzuzufügen. key-bind = "{enter: 'vm.doTheThing (' myVar ')'}"
MaylorTaylor
Auch bemerkt, dass, wenn ich Funktion mit einem Objekt als Variable verwende, die Funktion mehr als einmal passiert. Der folgende Code entfernt 2+ Elemente, wenn ich dies ausführe. key-bind = "{enter: 'vm.removeItem (item)'}"
MaylorTaylor
1
@MaylorTaylor für die erste Ausgabe, verwenden Sie verschiedene Arten von Zitaten, dh'vm.doTheThing("myVar")'
AlexFoxGill
14

Sehr gute, saubere und einfache Anweisung mit Shift + Enter-Unterstützung:

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
quelle
5

Wenn Sie auch eine Datenüberprüfung wünschen

<!-- 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>

Der wichtige Zusatz hier ist, $loginForm.$validder das Formular validiert, bevor die Funktion ausgeführt wird. Sie müssen andere Attribute zur Validierung hinzufügen, die den Rahmen dieser Frage sprengen.

Viel Glück.

Akash
quelle
2

Ich wollte nur darauf hinweisen, dass Sie im Fall einer versteckten Senden-Schaltfläche einfach die ngShow-Direktive verwenden und sie wie folgt auf false setzen können:

HTML

<form ng-submit="myFunc()">
    <input type="text" name="username">
    <input type="submit" value="submit" ng-show="false">
</form>
landesko
quelle
1
+1 <button ng-show="false"></button>ist noch kürzer. Der Wert einer unsichtbaren Schaltfläche muss nicht festgelegt werden.
Musa
Ich habe verstanden, dass zum Auslösen der ng-submit-Direktive eine Eingabe von type="submit"... Ich nehme an, der Wert könnte ignoriert werden, aber ich glaube, der erstere ist notwendig.
Landesko
1

Verwenden Sie ng-submit und verpacken Sie beide Eingaben in separate Formular-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>

Wenn Sie jedes Eingabefeld in ein eigenes Formular-Tag einschließen, kann ENTER in beiden Formularen die Übermittlung aufrufen. Wenn Sie für beide ein Formular-Tag verwenden, müssen Sie eine Senden-Schaltfläche einfügen.

Myclamm
quelle
0

Wird mit einer CSS-Klasse etwas ordentlicher sein, anstatt Inline-Stile zu wiederholen.

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
quelle
0

FWIW - Hier ist eine Anweisung, die ich für ein grundlegendes Bootstrap-Modal zur Bestätigung / Warnung verwendet habe, ohne dass ein <form>

(Schalten Sie einfach die jQuery-Klickaktion aus, was Sie möchten, und fügen Sie data-easy-dismisssie Ihrem modalen Tag hinzu.)

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);
            });
        }
    };
});
Andrew Appleby
quelle