Kirim formulir dengan menekan Enter dengan AngularJS


364

Dalam kasus khusus ini, opsi apa yang saya miliki untuk membuat input ini memanggil fungsi ketika saya menekan 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');
    };
}])

Jawaban:


518

Sudut mendukung ini di luar kotak. Sudahkah Anda mencoba ngSubmit pada elemen formulir Anda?

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

EDIT: Per komentar tentang tombol kirim, lihat Mengirimkan formulir dengan menekan enter tanpa tombol kirim yang memberikan solusi:

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

Jika Anda tidak menyukai solusi tombol kirim tersembunyi, Anda harus mengikat fungsi pengontrol ke acara Enter penekanan tombol atau keyup. Ini biasanya memerlukan arahan khusus, tetapi pustaka AngularUI sudah menyiapkan solusi penekanan tombol yang bagus. Lihat http://angular-ui.github.com/

Setelah menambahkan lib angularUI, kode Anda akan menjadi seperti:

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

atau Anda dapat mengikat tombol masuk ke setiap bidang individual.

Juga, lihat pertanyaan SO ini untuk membuat arahan keypres sederhana: Bagaimana cara mendeteksi onKeyUp di AngularJS?

EDIT (2014-08-28): Pada saat jawaban ini ditulis, ng-keypress / ng-keyup / ng-keydown tidak ada sebagai arahan asli di AngularJS. Dalam komentar di bawah ini @ darlan-alves memiliki solusi yang cukup bagus dengan:

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


9
Ini hanya berfungsi jika saya memiliki tombol kirim di dalam formulir juga.
ali

3
Perhatikan juga bahwa ini HAS untuk menjadi <form> sepertinya tidak berfungsi pada <someElement ng-form = "" ...> yang cenderung saya gunakan.
John Culviner

1
Hanya meninggalkan catatan: Jika Anda berakhir di sini dan mengirimkan tombol tidak berfungsi untuk Anda, Anda bisa menggunakan nama buruk untuk fungsi kirim Anda. Saya bodoh menggunakan ng-submit="join()"pengontrol registrasi yang memiliki $scope.join = function() {...}dan mengubah nama fungsi untuk foo()mendapatkan pengiriman tombol enter bekerja lagi.
tester

1
Pada saat jawaban ini ditulis, ng-keypress / ng-keyup tidak ada di Angular
eterps

69
ng-keyup="$event.keyCode == 13 && myFunc()"Sungguh luar biasa :)
Gonchar Denys

286

Jika Anda ingin memanggil fungsi tanpa formulir, Anda dapat menggunakan arahan ngEnter saya:

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>

Saya mengirimkan arahan luar biasa kepada orang lain di twitter dan akun utama saya .


2
Apakah ada cara pintar untuk memicu ini kapan saja mereka menekan enter saat berada di halaman Anda?
Derek Adair

1
@ EpokK Saya ingin menonaktifkan kunci enter untuk seluruh formulir, bagaimana saya bisa melakukannya? (Saya ingin menghindari pengiriman formulir dengan memasukkan)
Antonio Max

47
sangat bagus, tetapi sesuai rekomendasi AngularJs, Anda tidak boleh membuat arahan, layanan, atau filter yang diawali dengan ng, jika seandainya rilis resmi nanti menggunakan nama yang sama.
Neil S

5
Solusi bagus Saya baru saja mengubah nama menjadi keyBind dan baris ini "if (event.which === 13) {" to this "if (event.which === Number (attrs.key)) {" Lalu masukan saya ke "< tipe input = "text" bind-key = "doSomething ()" key = "13"> "sehingga saya bisa menggunakannya kembali untuk berbagai peristiwa penting.
Brian F

4
PENTING: Menambahkan keduanya keydowndan keypressacara tanpa koma untuk membatasi keduanya berarti keduanya dapat menyala secara bersamaan. Ini kemungkinan akan menghasilkan $ rootScope: kesalahan inprog. Menambahkan koma di antara mereka menciptakan disjungtif, dan memastikan hanya siklus $ digest yang terjadi. Tidak dapat menerapkan hasil edit karena hanya satu karakter.
Ryan Miller

197

Jika Anda hanya memiliki satu input, Anda dapat menggunakan tag formulir.

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

Jika Anda memiliki lebih dari satu input, atau tidak ingin menggunakan tag formulir, atau ingin melampirkan fungsionalitas tombol-enter ke bidang tertentu, Anda bisa memasukkannya ke input tertentu sebagai berikut:

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

2
Ini adalah cara cerdas untuk melakukan ini tanpa harus menulis arahan Anda sendiri
Charlie Martin

59
Bahkan lebih pendek: <input ng-keyup = "$ event.keyCode == 13 && myFunc ()" ... />
Darlan Alves

Berfungsi bagus, saya menggunakan arahan ng-keyup, tapi saya punya satu masalah besar dengan itu, jika saya hanya memiliki satu bidang teks, ia mengirimkan formulir lengkap (postback) tetapi saya tidak menginginkannya. Saya sudah mencoba ng-keyup = "$ event.keyCode == 13 && onTextBoxKeyUp ($ event)" dan dalam fungsi "event.preventDefault ();", tetapi tidak membantu; (
SharpNoiZy

ini lebih pendek tetapi menjaga pendekatan KERING dalam pikiran saya saya masih akan membuat arahan dan menggunakannya dengan arahan.
Atul Chaudhary

Ini mungkin bermasalah tergantung pada konteksnya - Saya memiliki bentuk di mana saya memiliki dua tombol, (antarmuka seperti penyihir), dengan tombol 'kembali' dan 'berikutnya', perilaku default mengklik tombol 'enter' adalah tombol kembali. Sekarang, ketika menggunakan kode di atas, tombol kembali mendapatkan CLICKED FIRST, dan kemudian kode myFunction () dipanggil (yang pada gilirannya, dapatkan ke bagian berikutnya dari wizard) Jadi, wizard saya akan KEMBALI untuk sementara waktu, dan kemudian maju. Solusi @ EpokK sangat cocok untuk saya.
Vishwajeet Vatharkar

33

Saya menginginkan sesuatu yang sedikit lebih extensible / semantik daripada jawaban yang diberikan jadi saya menulis arahan yang mengambil objek javascript dengan cara yang mirip dengan built-in ngClass:

HTML

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

Nilai-nilai objek dievaluasi dalam konteks ruang lingkup direktif - pastikan mereka terbungkus dalam tanda kutip tunggal jika tidak semua fungsi akan dieksekusi ketika direktif dimuat (!)

Jadi misalnya: esc : 'clear()'bukannyaesc : 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]);
                    });
                }
            });
        };
    }]);

Saya mendapatkan kesalahan parse HTML angluarjs ketika saya mencoba untuk menambahkan variabel string dalam fungsi. key-bind = "{enter: 'vm.doTheThing (' myVar ')'}"
MaylorTaylor

Juga perhatikan bahwa jika saya menggunakan fungsi dengan Objek sebagai variabel, fungsi terjadi lebih dari satu kali. Kode di bawah ini menghapus 2+ item ketika saya menjalankan ini. key-bind = "{enter: 'vm.removeItem (item)'}"
MaylorTaylor

1
@MaylorTaylor untuk masalah pertama, gunakan berbagai jenis kutipan yaitu'vm.doTheThing("myVar")'
AlexFoxGill


14

Sangat bagus, bersih dan arahan sederhana dengan dukungan 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

Jika Anda ingin validasi data juga

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

Tambahan penting di sini adalah $loginForm.$valid yang akan memvalidasi formulir sebelum menjalankan fungsi. Anda harus menambahkan atribut lain untuk validasi yang berada di luar cakupan pertanyaan ini.

Semoga berhasil.


2

Hanya ingin menunjukkan bahwa dalam kasus memiliki tombol kirim tersembunyi, Anda bisa menggunakan arahan ngShow dan mengaturnya ke false seperti:

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>bahkan lebih pendek. Tidak perlu mengatur nilai tombol yang tidak terlihat.
musa

Itu pemahaman saya bahwa untuk memicu arahan ng-submit, masukan dari type="submit"... Saya kira nilai bisa diabaikan tetapi saya percaya yang pertama diperlukan.
landesko

1

Gunakan ng-kirim dan bungkus kedua input dalam tag formulir terpisah:

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

Membungkus setiap bidang input dalam bentuknya sendiri memungkinkan ENTER untuk meminta pengiriman pada salah satu formulir. Jika Anda menggunakan satu tag formulir untuk keduanya, Anda harus memasukkan tombol kirim.


0

Akan sedikit lebih rapi menggunakan kelas CSS bukannya mengulang gaya inline.

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 - Ini adalah arahan yang saya gunakan untuk modal dasar konfirmasi / peringatan bootstrap, tanpa perlu a <form>

(cukup alihkan tindakan klik jQuery untuk apa pun yang Anda suka, dan tambahkan data-easy-dismisske tag modal Anda)

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);
            });
        }
    };
});
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.