Отправить форму по нажатию 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

Angular поддерживает это из коробки. Вы пробовали ngSubmit на элементе формы?

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

РЕДАКТИРОВАТЬ: В соответствии с комментарием, касающимся кнопки отправки, см. Отправка формы нажатием кнопки ввода без кнопки отправки, которая дает решение:

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

Если вам не нравится решение для скрытой кнопки отправки, вам нужно привязать функцию контроллера к событию Enter keypress или keyup. Обычно для этого требуется пользовательская директива, но в библиотеке AngularUI уже есть хорошее решение для нажатия клавиш. Смотрите http://angular-ui.github.com/

После добавления библиотеки angularUI ваш код будет выглядеть примерно так:

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

или вы можете привязать нажатие клавиши ввода к каждому отдельному полю.

Также см. Следующие вопросы о создании простой директивы keypres: Как я могу обнаружить onKeyUp в AngularJS?

РЕДАКТИРОВАТЬ (2014-08-28): На момент написания этого ответа ng-keypress / ng-keyup / ng-keydown не существовало как собственные директивы в AngularJS. В комментариях ниже @ darlan-alves предлагает довольно хорошее решение:

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

eterps
источник
9
Это работает, только если у меня есть кнопка отправки внутри формы тоже.
Али
3
Также обратите внимание, что это ДОЛЖНО быть <form>, похоже, оно не работает с <someElement ng-form = "" ...>, что я и склонен использовать.
Джон Кульвинер
1
Просто оставьте заметку: если вы оказались здесь и кнопки отправки не работают, вы можете использовать плохое имя для функции отправки. Я по-дурацки использовал ng-submit="join()"контроллер регистрации, у которого было, $scope.join = function() {...}и изменил имя этой функции, чтобы foo()снова заставить работать кнопку ввода.
тестер
1
На момент написания этого ответа в Angular не существовало ng-keypress / ng-
keyup
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>

Я отправляю другие потрясающие директивы на мой твиттер и мою учетную запись .

EpokK
источник
2
Есть ли умный способ заставить это срабатывать каждый раз, когда они нажимают ввод на вашей странице?
Дерек Адайр
1
@EpokK Я хочу отключить клавишу ввода для всей формы, как я могу это сделать? (Я хочу избежать отправки формы с вводом)
Антонио Макс
47
очень хорошо, но в соответствии с рекомендацией AngularJ, вы не должны создавать директивы, сервисы или фильтры с префиксом ng-, если в официальном выпуске позже используется то же имя.
Нил С
5
Отличное решение. Я просто изменил имя на keyBind и эту строку "if (event.which === 13) {" to this "if (event.which === Number (attrs.key)) {" И затем мой ввод в "< input type = "text" bind-key = "doSomething ()" key = "13"> ", чтобы я мог повторно использовать его для различных ключевых событий.
Брайан Ф
4
ВАЖНО: Добавление как keydownи keypressсобытия , без запятой , чтобы разграничить их означает и может стрелять одновременно. Это может привести к появлению ошибок $ rootScope: inprog. Добавление запятой между ними создает дизъюнктивный и гарантирует, что происходит только цикл $ digest. Не удалось применить редактирование, так как это всего лишь один символ.
Райан Миллер
197

Если у вас есть только один вход, вы можете использовать тег формы.

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

Если у вас более одного ввода, или вы не хотите использовать тег формы или хотите присоединить функциональность клавиши ввода к определенному полю, вы можете встроить его в определенный ввод следующим образом:

<input ng-keyup="$event.keyCode == 13 && myFunc()" ...>
М.М.
источник
2
Это умный способ сделать это даже без необходимости писать свою собственную директиву
Чарли Мартин
59
Еще короче: <input ng-keyup = "$ event.keyCode == 13 && myFunc ()" ... />
Дарлан Алвес
Прекрасно работает, я использовал директиву ng-keyup, но у меня есть одна большая проблема: если у меня только одно текстовое поле, он отправляет полную форму (постбэк), но я этого не хочу. Я уже пробовал ng-keyup = "$ event.keyCode == 13 && onTextBoxKeyUp ($ event)" и в функции "event.preventDefault ();", но не помогло; (
SharpNoiZy
это короче, но, помня о сухом подходе, я все равно создал бы директиву и использовал бы ее с директивой.
Атул Чаудхари
Это может быть проблематично в зависимости от контекста - у меня есть форма, в которой у меня есть две кнопки (интерфейс, подобный мастеру), с кнопками «назад» и «далее», поведение по умолчанию при нажатии клавиши «ввод» - кнопка назад. Теперь, при использовании приведенного выше кода, кнопка «Назад» получает CLICKED FIRST, а затем вызывается код myFunction () (который, в свою очередь, переходит к следующей части мастера). Итак, мой мастер некоторое время возвращается назад, а затем идет вперед. Решение @ EpokK идеально подходит для меня.
Вишваджит Ватхаркар
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]);
                    });
                }
            });
        };
    }]);
AlexFoxGill
источник
Я получаю ошибку HTML-разбора angluarjs при попытке добавить строковую переменную в функцию. key-bind = "{enter: 'vm.doTheThing (' myVar ')'}"
MaylorTaylor
Также заметил, что если я использую функцию с Объектом в качестве переменной, функция происходит более одного раза. Код ниже удаляет 2+ элемента, когда я запускаю это. key-bind = "{enter: 'vm.removeItem (item)'}"
MaylorTaylor
1
@MaylorTaylor для первого выпуска, используйте различные типы цитат, т. 'vm.doTheThing("myVar")'
Е.
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);
                       }
                 }
            });
        }
    }
});
Vlatko
источник
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>
landesko
источник
1
+1 <button ng-show="false"></button>еще короче. Не нужно устанавливать значение невидимой кнопки.
Musa
type="submit"Насколько я понимаю, для запуска директивы ng-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 вызывать submit в любой форме. Если вы используете один тег формы для обоих, вам нужно будет включить кнопку отправки.

Myclamm
источник
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>
Guya
источник
0

FWIW - вот директива, которую я использовал для базового модала подтверждения / предупреждения, без необходимости <form>

(просто отключите действие jQuery click для всего, что вам нравится, и добавьте 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);
            });
        }
    };
});
Эндрю Эпплби
источник