ส่งแบบฟอร์มเมื่อกด Enter ด้วย AngularJS


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

เชิงมุมรองรับสิ่งนี้นอกกรอบ คุณได้ลอง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>

หรือคุณสามารถผูกปุ่มกดสำหรับแต่ละฟิลด์

ดูคำถาม SO นี้เพื่อสร้างคำสั่ง keypres แบบง่าย: ฉันจะตรวจหา onKeyUp ใน AngularJS ได้อย่างไร

แก้ไข (2014-08-28): ในขณะที่เขียนคำตอบนี้ ng-keypress / ng-keyup / ng-keydown ไม่มีอยู่ในคำสั่งดั้งเดิมใน AngularJS ในความคิดเห็นด้านล่าง @ darlan-alves มีทางออกที่ดีงามด้วย:

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


9
ใช้งานได้เฉพาะถ้าฉันมีปุ่มส่งภายในฟอร์มด้วย
ali

3
โปรดทราบด้วยว่า HAS นี้จะเป็น <form> ดูเหมือนจะไม่สามารถใช้งานได้ <someElement ng-form = "" ... > ซึ่งเป็นสิ่งที่ฉันมักจะใช้
John Culviner

1
เพียงแค่ทิ้งโน้ต: หากคุณลงเอยที่นี่และปุ่มส่งไม่ทำงานสำหรับคุณคุณอาจใช้ชื่อที่ไม่ดีสำหรับฟังก์ชั่นส่งของคุณ ฉันใช้ng-submit="join()"ตัวควบคุมการลงทะเบียนที่โง่$scope.join = function() {...}และเปลี่ยนชื่อฟังก์ชันนั้นเพื่อให้foo()การส่งปุ่ม Enter ทำงานได้อีกครั้ง
ผู้ทดสอบ

1
ในขณะที่เขียนคำตอบนี้ ng-keypress / ng-keyup ไม่มีอยู่ใน Angular
eterps

69
ng-keyup="$event.keyCode == 13 && myFunc()"เจ๋งมาก :) :)
Gonchar Denys

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>

ฉันส่งคำสั่งอื่น ๆ ที่น่ากลัวในTwitterและบัญชีสรุปของฉัน


2
มีวิธีที่ชาญฉลาดในการทำให้สิ่งนี้เรียกใช้เมื่อใดก็ตามที่พวกเขากด Enter ขณะอยู่บนหน้าเว็บของคุณ?
Derek Adair

1
@EpokK ฉันต้องการปิดใช้งานคีย์ Enter สำหรับทั้งฟอร์มฉันจะทำอย่างไร (ฉันต้องการหลีกเลี่ยงการส่งแบบฟอร์มด้วยการป้อน)
อันโตนิโอแม็กซ์

47
ดีมาก แต่ตามคำแนะนำของ AngularJs คุณไม่ควรสร้างคำสั่งบริการหรือตัวกรองที่มีคำนำหน้าด้วย ng- ในกรณีที่รีลีสอย่างเป็นทางการใช้ชื่อเดียวกันในภายหลัง
Neil S

5
ทางออกที่ดี ฉันเพิ่งเปลี่ยนชื่อเป็น keyBind และบรรทัดนี้ "if (event.which === 13) {" เปลี่ยนเป็น "ถ้า (event.which === หมายเลข (attrs.key)) {" จากนั้นอินพุตของฉันเป็น "< input type = "text" bind-key = "doSomething ()" key = "13"> "เพื่อที่ฉันจะสามารถนำมันกลับมาใช้ใหม่ได้สำหรับเหตุการณ์สำคัญต่างๆ
Brian F

4
สำคัญ: การเพิ่มทั้งสองkeydownและkeypressเหตุการณ์โดยไม่มีเครื่องหมายจุลภาคเพื่อคั่นพวกเขาหมายความว่าทั้งสองอาจยิงพร้อมกัน สิ่งนี้มีแนวโน้มที่จะเกิดข้อผิดพลาด $ rootScope: inprog เพิ่มเครื่องหมายจุลภาคระหว่างพวกเขาสร้าง disjunctive และให้แน่ใจว่าเกิดขึ้นเพียงแค่ $ แยกวงจร ไม่สามารถใช้การแก้ไขเนื่องจากเป็นเพียงอักขระเดียวเท่านั้น
Ryan Miller

197

หากคุณมีเพียงอินพุตเดียวคุณสามารถใช้แท็กแบบฟอร์ม

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

หากคุณมีมากกว่าหนึ่งอินพุตหรือไม่ต้องการใช้แท็กแบบฟอร์มหรือต้องการแนบฟังก์ชันการทำงานของคีย์ - คีย์กับฟิลด์ที่ระบุคุณสามารถอินไลน์เข้ากับอินพุตเฉพาะดังนี้:

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

2
นี่เป็นวิธีที่ฉลาดในการทำสิ่งนี้โดยไม่ต้องเขียนคำสั่งของคุณเอง
Charlie Martin

59
ยิ่งสั้นกว่า: <input ng-keyup = "$ event.keyCode == 13 && myFunc ()" ... />
Darlan Alves

ใช้งานได้ดีฉันใช้คำสั่ง ng-keyup แต่ฉันมีปัญหาใหญ่กับมันถ้าฉันมีเพียงหนึ่งช่องข้อความเขาส่งแบบฟอร์มที่สมบูรณ์ (postback) แต่ฉันไม่ต้องการมัน ฉันลองแล้ว ng-keyup = "$ event.keyCode == 13 && onTextBoxKeyUp ($ event)" และในฟังก์ชั่น "event.preventDefault ();" แต่ไม่ช่วย; (
SharpNoiZy

นี่จะสั้นกว่า แต่รักษาแนวทาง DRY ไว้ในใจฉันจะยังคงสร้างคำสั่งและใช้มันด้วยคำสั่ง
Atul Chaudhary

นี่อาจเป็นปัญหาขึ้นอยู่กับบริบท - ฉันมีรูปแบบที่ฉันมีสองปุ่ม (ตัวช่วยสร้างเช่นอินเทอร์เฟซ) ด้วยปุ่ม 'ย้อนกลับ' และ 'ถัดไป' พฤติกรรมเริ่มต้นเมื่อคลิกปุ่ม 'Enter' คือปุ่มย้อนกลับ ตอนนี้เมื่อใช้โค้ดด้านบนปุ่มย้อนกลับจะได้รับการคลิกครั้งแรกจากนั้นรหัส myFunction () จะถูกเรียก (ซึ่งจะกลับไปสู่ส่วนถัดไปของตัวช่วยสร้าง) ดังนั้นตัวช่วยสร้างของฉันจะย้อนกลับไปครู่หนึ่ง @ โซลูชันของ EpokK นั้นสมบูรณ์แบบสำหรับฉัน
Vishwajeet Vatharkar

33

ฉันต้องการบางสิ่งบางอย่างที่สามารถขยายได้ / ความหมายมากกว่าคำตอบที่ได้รับเล็กน้อยดังนั้นฉันจึงเขียนคำสั่งที่ใช้วัตถุจาวาสคริปต์ในลักษณะเดียวกันกับที่มีในตัวngClass:

HTML

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

ค่าของวัตถุได้รับการประเมินในบริบทของขอบเขตของ directive - ตรวจสอบให้แน่ใจว่าพวกเขาถูกห่อหุ้มด้วยเครื่องหมายคำพูดเดี่ยวมิฉะนั้นฟังก์ชั่นทั้งหมดจะถูกดำเนินการเมื่อโหลดคำสั่ง (!)

ตัวอย่างเช่น: esc : 'clear()'แทนesc : clear()

จาวาสคริ

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

ฉันได้รับข้อผิดพลาดในการแยกวิเคราะห์ HTML ของ angluarjs เมื่อฉันพยายามเพิ่มตัวแปรสตริงในฟังก์ชัน key-bind = "{ป้อน: 'vm.doTheThing (' myVar ')'}"
MaylorTaylor

สังเกตว่าถ้าฉันใช้ฟังก์ชันกับวัตถุเป็นตัวแปรฟังก์ชันจะเกิดขึ้นมากกว่าหนึ่งครั้ง รหัสด้านล่างลบ 2+ รายการเมื่อฉันเรียกใช้ key-bind = "{ป้อน: 'vm.removeItem (รายการ)'}"
MaylorTaylor

1
@MaylorTaylor สำหรับปัญหาแรกให้ใช้คำพูดประเภทต่าง ๆ เช่น'vm.doTheThing("myVar")'
AlexFoxGill


14

คำสั่งดีมากสะอาดและเรียบง่ายพร้อม shift + enter support:

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 และตั้งค่าเป็นเท็จเช่นนั้น:

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>ยิ่งสั้น ไม่จำเป็นต้องตั้งค่าของปุ่มที่มองไม่เห็น
มูซา

มันเป็นความเข้าใจของฉันว่าในการสั่งการ 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 เรียกใช้การส่งแบบฟอร์มใดก็ได้ หากคุณใช้แท็กฟอร์มหนึ่งแท็กสำหรับทั้งคู่คุณจะต้องรวมปุ่มส่ง


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 - ต่อไปนี้เป็นคำสั่งที่ฉันใช้สำหรับการยืนยัน / การแจ้งเตือน bootstrap แบบพื้นฐานโดยไม่จำเป็นต้องใช้ <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.