Gửi biểu mẫu khi nhấn Enter với AngularJS


364

Trong trường hợp cụ thể này, tôi có những tùy chọn nào để làm cho các đầu vào này gọi một hàm khi tôi nhấn 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');
    };
}])

Câu trả lời:


518

Angular hỗ trợ này ra khỏi hộp. Bạn đã thử ngSubmit trên phần tử biểu mẫu của bạn chưa?

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

EDIT: Mỗi nhận xét liên quan đến nút gửi, hãy xem Gửi biểu mẫu bằng cách nhấn enter mà không có nút gửi sẽ đưa ra giải pháp:

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

Nếu bạn không thích giải pháp nút gửi ẩn, bạn sẽ cần liên kết một chức năng của bộ điều khiển với sự kiện nhấn phím hoặc nhấn phím. Điều này thường yêu cầu một chỉ thị tùy chỉnh, nhưng thư viện AngularUI đã có một giải pháp nhấn phím đẹp mắt. Xem http://angular-ui.github.com/

Sau khi thêm lib angularUI, mã của bạn sẽ giống như:

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

hoặc bạn có thể liên kết phím nhấn vào từng trường riêng lẻ.

Ngoài ra, hãy xem câu hỏi SO này để tạo một lệnh keypres đơn giản: Làm cách nào tôi có thể phát hiện onKeyUp trong AngularJS?

EDIT (2014-08-28): Tại thời điểm câu trả lời này được viết, ng-keypress / ng-keyup / ng-keydown không tồn tại như các chỉ thị gốc trong AngularJS. Trong các ý kiến ​​dưới đây @ darlan-alves có một giải pháp khá hay với:

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


9
Nó chỉ hoạt động nếu tôi có một nút gửi trong biểu mẫu, quá.
ali

3
Cũng lưu ý rằng điều này đã trở thành một <form> nó dường như không hoạt động trên <someEuity ng-form = "" ...> đó là những gì tôi có xu hướng sử dụng.
John Culviner

1
Chỉ cần để lại một ghi chú: Nếu bạn đã kết thúc ở đây và gửi các nút không hoạt động cho bạn, bạn có thể đang sử dụng một tên xấu cho chức năng gửi của bạn. Tôi đã dại dột sử dụng ng-submit="join()"cho một bộ điều khiển đăng ký đã có $scope.join = function() {...}và thay đổi tên hàm đó để foo()gửi nút nhập hoạt động trở lại.
người kiểm tra

1
Tại thời điểm câu trả lời này được viết, ng-keypress / ng-keyup không tồn tại trong Angular
eterps

69
ng-keyup="$event.keyCode == 13 && myFunc()"Thực sự tuyệt vời :)
Gonchar Denys

286

Nếu bạn muốn gọi hàm mà không cần biểu mẫu, bạn có thể sử dụng lệnh ng Entry của tôi:

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>

Tôi gửi cho người khác những chỉ thị tuyệt vời trên twittertài khoản chính của tôi .


2
Có cách nào thông minh để kích hoạt tính năng này bất cứ khi nào họ nhấn enter khi ở trên trang của bạn không?
Derek Adair

1
@EpokK Tôi muốn vô hiệu hóa phím enter cho toàn bộ biểu mẫu, làm thế nào tôi có thể làm điều đó? (Tôi muốn tránh gửi biểu mẫu bằng enter)
Antonio Max

47
rất hay, nhưng theo lời giới thiệu của AngularJs, bạn không nên tạo các chỉ thị, dịch vụ hoặc bộ lọc có tiền tố ng-, trong trường hợp bản phát hành chính thức sau đó sử dụng cùng tên.
Neil S

5
Giải pháp tuyệt vời. Tôi vừa đổi tên thành keyBind và dòng này "if (event.which === 13) {" thành this "if (event.which === Number (attrs.key)) {" Và sau đó, đầu vào của tôi thành "< input type = "text" bind-key = "doS Something ()" key = "13"> "để tôi có thể sử dụng lại nó cho các sự kiện quan trọng khác nhau.
Brian F

4
QUAN TRỌNG: Thêm cả sự kiện keydownkeypresssự kiện mà không có dấu phẩy để phân định chúng có nghĩa là cả hai có thể bắn đồng thời. Điều này có khả năng sinh ra $ rootScope: lỗi inprog. Thêm dấu phẩy giữa chúng sẽ tạo ra sự khác biệt và chỉ đảm bảo chỉ xảy ra chu kỳ $ digest. Không thể áp dụng chỉnh sửa vì nó chỉ là một ký tự.
Ryan Miller

197

Nếu bạn chỉ có một đầu vào, bạn có thể sử dụng thẻ biểu mẫu.

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

Nếu bạn có nhiều đầu vào hoặc không muốn sử dụng thẻ biểu mẫu hoặc muốn đính kèm chức năng nhập khóa vào một trường cụ thể, bạn có thể đặt nội tuyến vào một đầu vào cụ thể như sau:

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

2
Đây là một cách thông minh để làm điều này mà không cần phải viết chỉ thị của riêng bạn
Charlie Martin

59
Thậm chí ngắn hơn: <input ng-keyup = "$ event.keyCode == 13 && myFunc ()" ... />
Darlan Alves

Hoạt động rất tốt, tôi đã sử dụng chỉ thị ng-keyup, nhưng tôi có một vấn đề lớn với nó, nếu tôi chỉ có một trường văn bản, anh ấy sẽ gửi biểu mẫu hoàn chỉnh (postback) nhưng tôi không muốn điều đó. Tôi đã cố gắng đã ng-KeyUp = "$ event.keyCode == 13 && onTextBoxKeyUp ($ sự kiện)" và trong chức năng "event.preventDefault ();", nhưng đã không thể giúp ích; (
SharpNoiZy

Điều này ngắn hơn nhưng giữ cách tiếp cận DRY trong tâm trí tôi vẫn sẽ tạo ra chỉ thị và sử dụng nó với chỉ thị.
Atul Chaudhary

Điều này có thể có vấn đề tùy thuộc vào ngữ cảnh - Tôi có một hình thức trong đó tôi có hai nút, (giao diện giống như trình hướng dẫn), với nút 'quay lại' và 'tiếp theo', hành vi mặc định khi nhấp vào phím 'enter' là nút quay lại. Bây giờ, khi sử dụng mã ở trên, nút quay lại sẽ được NHẤP VÀO ĐẦU TIÊN, và sau đó mã myFactor () được gọi (lần lượt, chuyển sang phần tiếp theo của trình hướng dẫn) Vì vậy, trình hướng dẫn của tôi sẽ TRỞ LẠI một lúc, rồi nó tiếp tục. Giải pháp của EpokK hoàn hảo cho tôi.
Vishwajeet Vatharkar

33

Tôi muốn một cái gì đó mở rộng / ngữ nghĩa hơn một chút so với các câu trả lời đã cho nên tôi đã viết một lệnh lấy một đối tượng javascript theo cách tương tự như tích hợp ngClass:

HTML

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

Các giá trị của đối tượng được đánh giá trong ngữ cảnh phạm vi của lệnh - đảm bảo chúng được đặt trong các dấu ngoặc đơn nếu không tất cả các hàm sẽ được thực thi khi lệnh được tải (!)

Vì vậy, ví dụ: esc : 'clear()'thay vì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]);
                    });
                }
            });
        };
    }]);

Tôi gặp lỗi phân tích cú pháp HTML angluarjs khi tôi cố gắng thêm một biến chuỗi trong hàm. key-bind = "{enter: 'vm.doTheThing (' myVar ')'}"
MaylorTaylor

Cũng lưu ý rằng nếu tôi sử dụng hàm với Object làm biến, thì hàm xảy ra nhiều lần. Mã dưới đây loại bỏ 2+ mục khi tôi chạy này. key-bind = "{enter: 'vm.removeItem (mục)'}"
MaylorTaylor

1
@MaylorTaylor cho vấn đề đầu tiên, sử dụng các loại trích dẫn khác nhau tức là'vm.doTheThing("myVar")'
AlexFoxGill


14

Rất tốt, sạch sẽ và chỉ thị đơn giản với sự thay đổi + nhập hỗ trợ:

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

Nếu bạn muốn xác thực dữ liệu quá

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

Bổ sung quan trọng ở đây là $loginForm.$validsẽ xác nhận mẫu trước khi thực hiện chức năng. Bạn sẽ phải thêm các thuộc tính khác để xác thực nằm ngoài phạm vi của câu hỏi này.

Chúc may mắn.


2

Chỉ muốn chỉ ra rằng trong trường hợp có nút gửi ẩn, bạn có thể chỉ cần sử dụng lệnh ngShow và đặt thành sai như vậy:

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>thậm chí còn ngắn hơn. Không cần thiết lập giá trị của một nút vô hình.
musa

Theo hiểu biết của tôi, để kích hoạt chỉ thị ng-submit, một đầu vào của type="submit"... Tôi cho rằng giá trị có thể bị bỏ qua nhưng tôi tin rằng trước đây là cần thiết.
Landesko

1

Sử dụng ng-submit và chỉ bọc cả hai đầu vào trong các thẻ mẫu riêng biệt:

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

Việc gói từng trường đầu vào trong thẻ biểu mẫu riêng của nó cho phép ENTER gọi trình trên cả hai biểu mẫu. Nếu bạn sử dụng một thẻ biểu mẫu cho cả hai, bạn sẽ phải bao gồm nút gửi.


0

Sẽ gọn gàng hơn khi sử dụng lớp CSS thay vì lặp lại các kiểu nội tuyến.

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 - Đây là một lệnh tôi đã sử dụng cho một phương thức bootstrap xác nhận / cảnh báo cơ bản, mà không cần phải có <form>

(chỉ cần tắt hành động nhấp chuột jQuery cho bất cứ điều gì bạn thích và thêm data-easy-dismissvào thẻ phương thức của bạn)

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);
            });
        }
    };
});
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.