Надішліть форму при натисканні клавіші 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 або клавіші Enter. Для цього зазвичай потрібна спеціальна директива, але в бібліотеці AngularUI вже створено приємне рішення для натискання клавіш. Дивіться http://angular-ui.github.com/

Після додавання вкладки angularUI ваш код стане приблизно таким:

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

або ви можете прив’язати клавішу введення до кожного окремого поля.

Також дивіться це питання ТА для створення простої директиви keypress: Як я можу виявити onKeyUp в AngularJS?

EDIT (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 = "" ...> що я, як правило, використовую.
Джон Кальвінер

1
Лише зауваження: Якщо ви закінчилися тут, кнопки для надсилання не працюють для вас, ви можете використовувати неправильне ім’я для функції подання. Я нерозумно використовував ng-submit="join()"для контролера реєстрації, який мав $scope.join = function() {...}та змінив цю назву функції, щоб foo()знову надіслати кнопку введення.
тестер

1
На момент написання цієї відповіді, ng-keypress / ng-keyup не існувало у Angular
eterps

69
ng-keyup="$event.keyCode == 13 && myFunc()"Дійсно приголомшливий :)
Гончар Денис

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
Чи є розумний спосіб змусити це запустити будь-який момент, коли вони потрапляють, увійшовши на вашу сторінку?
Дерек Адаїр

1
@EpokK Я хочу відключити клавішу введення для всієї форми, як це зробити? (Я хочу уникнути подання форми при введенні)
Антоніо Макс

47
дуже добре, але згідно з рекомендацією AngularJs, ви не повинні створювати директиви, служби чи фільтри, які мають префікс ng-, якщо офіційний реліз згодом використовує те саме ім’я.
Ніл S

5
Прекрасне рішення. Я щойно змінив ім'я на keyBind та цей рядок "if (event.which === 13) {" to this "if (event.which === Number (attrs.key)) {" І тоді мій внесок на "< type type = "text" bind-key = "doSomething ()" key = "13"> ", щоб я міг повторно використовувати його для різних ключових подій.
Брайан F

4
ВАЖЛИВО: Додавання обох keydownта keypressподій без коми для їх розмежування означає, що обидва можуть запускатись одночасно. Це, ймовірно, породжує $ rootScope: помилки в програмі. Додавання кома між ними створює диз'юнктив і забезпечує лише цикл перетворення $ $. Неможливо застосувати редагування, оскільки це лише один символ.
Райан Міллер

197

Якщо у вас є лише один вхід, ви можете використовувати тег форми.

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

Якщо у вас є більше одного введення, або ви не хочете використовувати тег форми, або хочете приєднати функціональний ключ клавіші до певного поля, ви можете вкласти його до конкретного вводу таким чином:

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

2
Це розумний спосіб зробити це, навіть не будучи писати власну директиву
Чарлі Мартін

59
Ще коротше: <input ng-keyup = "$ event.keyCode == 13 && myFunc ()" ... />
Darlan Alves

Відмінно працює, я використав директиву ng-keyup, але у мене є одна велика проблема з нею, якщо у мене є лише одне текстове поле, він подає повну форму (postback), але я цього не хочу. Я вже спробував ng-keyup = "$ event.keyCode == 13 && onTextBoxKeyUp ($ подія)" та у функції "event.preventDefault ();", але не допомогло; (
SharpNoiZy

це коротше, але, маючи на увазі сухий підхід, я все одно буду створювати директиви та використовувати його з директивою.
Atul Chaudhary

Це може бути проблематично в залежності від контексту - у мене є форма, в якій я маю дві кнопки (як майстер, як інтерфейс), з кнопкою «назад» та «наступний», поведінка за замовчуванням при натисканні клавіші «введення» - це кнопка «назад». Тепер при використанні вищевказаного коду кнопкою "назад" стає "КЛІКОВАНО ПЕРШО", а потім викликається код 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]);
                    });
                }
            });
        };
    }]);

Коли я намагаюся додати змінну рядка у функції, я отримую помилку розбору HTML angluarjs. key-bind = "{enter: 'vm.doTheThing (' myVar ')'}"
MaylorTaylor

Також зауважив, що якщо я використовую функцію з Об'єктом як змінну, ця функція трапляється не один раз. Код нижче видаляю 2+ елементів, коли я запускаю цей. key-bind = "{enter: 'vm.removeItem (item)'}"
MaylorTaylor

1
@MaylorTaylor для першого випуску використовуйте різні типи цитат, тобто'vm.doTheThing("myVar")'
AlexFoxGill


14

Дуже хороша, чиста та проста директива зі зміною + введіть підтримку:

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>ще коротше. Не потрібно встановлювати значення невидимої кнопки.
musa

Я розумів, що для того, щоб запустити директиву 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 - Ось директива, яку я використав для базового модального режиму завантаження / оповіщення, без необхідності <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);
            });
        }
    };
});
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.