AngularJSでEnterキーを押してフォームを送信する


364

この特定のケースでは、Enterキーを押したときにこれらの入力が関数を呼び出すようにするにはどのようなオプションが必要ですか?

// 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');
    };
}])

回答:


518

Angularはこれをそのままサポートします。フォーム要素でngSubmitを試しましたか?

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

編集:送信ボタンに関するコメントに従って、次の解決策を提供する送信ボタンなしでEnterキーを押してフォームを送信するを参照してください。

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

非表示の送信ボタンソリューションが気に入らない場合は、コントローラー関数をEnterキープレスまたはキーアップイベントにバインドする必要があります。通常、これにはカスタムディレクティブが必要ですが、AngularUIライブラリにはすでにすばらしいキープレスソリューションが設定されています。http://angular-ui.github.com/を参照してください

angularUI libを追加すると、コードは次のようになります。

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

または、Enterキーを個別のフィールドにバインドできます。

また、単純なkeypresディレクティブの作成については、SOの質問を参照してください 。AngularJSでonKeyUpを検出するにはどうすればよいですか?

編集(2014-08-28):この回答が書かれた時点で、ng-keypress / ng-keyup / ng-keydownはAngularJSのネイティブディレクティブとして存在していませんでした。以下のコメントで、@ darlan-alvesは次のようなかなり良い解決策を持っています。

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


9
フォーム内に送信ボタンがある場合にのみ機能します。
アリ

3
また、これは<form>である必要があることに注意してください。これは、私がよく使用する<someElement ng-form = "" ...>では機能しないようです。
John Culviner 2014年

1
メモを残してください:ここまで来て送信ボタンが機能しない場合は、送信関数に不適切な名前を使用している可能性があります。私は愚かng-submit="join()"にも、$scope.join = function() {...}その関数名を持っている登録コントローラーに使用していて、foo()Enterボタンの送信が再び機能するように変更していました。
テスター

1
この回答が書かれた時点では、ng-keypress / ng-keyupはAngularに存在していませんでした
eterps 14

69
ng-keyup="$event.keyCode == 13 && myFunc()"本当に素晴らしい:)
Gonchar Denys '19

286

フォームなしで関数を呼び出したい場合は、ngEnterディレクティブを使用できます。

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>

私は他の素晴らしいディレクティブを私のツイッターと私の要旨のアカウントで提出します


2
これがページ上でEnterキーを押したときにトリガーする巧妙な方法はありますか?
デレク・アデア

1
@EpokKフォーム全体のEnterキーを無効にしたいのですが、どうすればよいですか?(Enterによるフォームの送信は避けたい)
Antonio Max

47
非常に良いですが、AngularJの推奨事項に従って、公式リリースで後で同じ名前が使用される場合に備えて、ng-で始まるディレクティブ、サービス、またはフィルターを作成しないでください。
Neil S

5
素晴らしいソリューション。名前をkeyBindに変更し、この行 "if(event.which === 13){"をこの "if(event.which === Number(attrs.key)){"に変更してから、 "< input type = "text" bind-key = "doSomething()" key = "13"> "にして、さまざまなキーイベントに再利用できるようにします。
ブライアンF

4
重要:keydownkeypressイベントの両方をカンマなしで追加してそれらを区切ると、両方が同時に発生する可能性があります。これにより、$ rootScope:inprogエラーが発生する可能性があります。それらの間にコンマを追加すると、選言が作成され、$ digestサイクルのみが発生するようになります。単一の文字であるため、編集を適用できませんでした。
Ryan Miller 14

197

入力が1つしかない場合は、formタグを使用できます。

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

複数の入力がある場合、フォームタグを使用しない場合、または特定のフィールドにEnterキー機能をアタッチする場合は、次のように特定の入力にインライン化できます。

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

2
これは、独自のディレクティブを作成することなく、これを行う賢い方法です
チャーリーマーティン

59
さらに短く:<input ng-keyup = "$ event.keyCode == 13 && myFunc()" ... />
Darlan Alves

うまく動作し、ng-keyupディレクティブを使用しましたが、1つの大きな問題があります。テキストフィールドが1つしかない場合、完全なフォーム(ポストバック)を送信しますが、それは望みません。私はすでにng-keyup = "$ event.keyCode == 13 && onTextBoxKeyUp($ event)"および関数 "event.preventDefault();"で試しましたが、助けにはなりませんでした;(
SharpNoiZy

これは短いですが、DRYのアプローチを心に留めながら、ディレクティブを作成してディレクティブで使用します。
Atul Chaudhary 2015

これは、状況によっては問題になる可能性があります。「戻る」ボタンと「次へ」ボタンを備えた2つのボタン(インターフェースのようなウィザード)があり、「Enter」キーをクリックしたときのデフォルトの動作は戻るボタンです。さて、上記のコードを使用すると、戻るボタンが最初にクリックされ、次にmyFunction()コードが呼び出されます(次に、ウィザードの次の部分に進みます)したがって、ウィザードはしばらく戻ってから、次に進みます。@EpokKのソリューションは私にぴったりです。
Vishwajeet Vatharkar

33

私は与えられた答えよりも少し拡張可能/意味的なものが欲しかったので、組み込みのものと同様の方法でjavascriptオブジェクトを取るディレクティブを書きましたngClass

HTML

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

オブジェクトの値は、ディレクティブのスコープのコンテキストで評価されます。値が一重引用符で囲まれていることを確認してください。そうでない場合、ディレクティブが読み込まれたときにすべての関数が実行されます(!)

だから例えば:の esc : 'clear()'代わりに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]);
                    });
                }
            });
        };
    }]);

関数に文字列変数を追加しようとすると、angluarjs HTML解析エラーが発生します。key-bind = "{enter: 'vm.doTheThing(' myVar ')'}"
MaylorTaylor

また、オブジェクトを変数として関数を使用すると、関数が複数回発生することにも注意してください。以下のコードは、これを実行すると2つ以上の項目を削除します。key-bind = "{Enter: 'vm.removeItem(item)'}"
MaylorTaylor

1
最初の問題のため@MaylorTaylor、すなわち引用符の異なる種類を使用する'vm.doTheThing("myVar")'
AlexFoxGill


14

Shift + Enterをサポートする非常に優れたクリーンでシンプルなディレクティブ:

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);
                       }
                 }
            });
        }
    }
});

5

データ検証も必要な場合

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

ここで重要な追加は$loginForm.$valid、関数を実行する前にフォームを検証することです。この質問の範囲を超える検証のために他の属性を追加する必要があります。

幸運を。


2

非表示の送信ボタンがある場合は、ngShowディレクティブを使用して、次のようにfalseに設定できることを指摘したかっただけです。

HTML

<form ng-submit="myFunc()">
    <input type="text" name="username">
    <input type="submit" value="submit" ng-show="false">
</form>

1
+1 <button ng-show="false"></button>はさらに短くなります。非表示のボタンの値を設定する必要はありません。
musa 2017

ng-submitディレクティブをトリガーするためにtype="submit"...の入力を無視できると思いますが、前者が必要であると私は理解しています。
landesko

1

ng-submitを使用して、両方の入力を別々のフォームタグでラップするだけです。

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

各入力フィールドを独自のフォームタグでラップすると、ENTERはどちらのフォームでも送信を呼び出すことができます。両方に1つのフォームタグを使用する場合は、送信ボタンを含める必要があります。


0

インラインスタイルを繰り返すのではなく、CSSクラスを使用すると、少しすっきりします。

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>

0

FWIW-以下は、基本的な確認/アラートブートストラップモーダルに使用したディレクティブです。 <form>

(jQueryクリックアクションを好きなように切り替えて、data-easy-dismissモーダルタグに追加するだけです)

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);
            });
        }
    };
});
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.