Как использовать событие нажатия клавиш в AngularJS?

410

Я хочу поймать событие нажатия клавиши ввода в текстовом поле ниже. Чтобы было понятнее, я использую ng-repeatдля заполнения текст. Вот HTML-код:

<td><input type="number" id="closeqty{{$index}}" class="pagination-right closefield" 
    data-ng-model="closeqtymodel" data-ng-change="change($index)" required placeholder="{{item.closeMeasure}}" /></td>

Это мой модуль:

angular.module('components', ['ngResource']);

Я использую ресурс для заполнения таблицы, и мой код контроллера:

function Ajaxy($scope, $resource) {
//controller which has resource to populate the table 
}
Венката Тата
источник
1
Вход внутри формы?
callmekatootie
1
нет .. это в таблице!
Венката Тата

Ответы:

808

Вам нужно добавить directive, как это:

Javascript :

app.directive('myEnter', function () {
    return function (scope, element, attrs) {
        element.bind("keydown keypress", function (event) {
            if(event.which === 13) {
                scope.$apply(function (){
                    scope.$eval(attrs.myEnter);
                });

                event.preventDefault();
            }
        });
    };
});

HTML :

<div ng-app="" ng-controller="MainCtrl">
    <input type="text" my-enter="doSomething()">    
</div>
EpokK
источник
7
@DerekAdair Директива привязывает события keydownи keypressк элементу, которому она приписана. Когда событие получено, предоставленное выражение оценивается внутри $applyблока.
Пит Мартин
7
Более безопасно определить ключ следующим образом: var key = typeof event.which === "undefined" ? event.keyCode : event.which;до тех пор, пока event.which не используется каждым браузером. Смотрите комментарии здесь: stackoverflow.com/a/4471635/2547632
Габриэль
3
Я бы добавил также keyupв тесте связывания
user1713964
59
Также обратите внимание, что использование префикса ng не рекомендуется, так как это может противоречить будущим директивам ng- *. Вместо этого используйте свой собственный
Marius Balčytis
3
Не забудьте уничтожить ваши привязки: scope. $ On ('$ destroy', function () {element.unbind ('keydown');})
nawlbergs
345

Альтернативой является использование стандартной директивы ng-keypress="myFunct($event)"

Тогда в вашем контроллере вы можете иметь:

...

$scope.myFunct = function(keyEvent) {
  if (keyEvent.which === 13)
    alert('I am an alert');
}

...
Крис Рейнольдс
источник
18
Для того, чтобы спасти других людей некоторое время, ng-keypressкажется, не быть частью углового 1.0.x, ui-keypress(с несколько различных вызовов семантикой) доступен , хотя: angular-ui.github.io/ui-utils
Cebjyre
1
Я думаю, что комментарий выше этого был направлен на другой ответ. (Только для справки.)
Корнелиус
Мартин, на самом деле это функция контроллера: обрабатывать события пользовательского интерфейса.
Тревор де Коеккук
5
А еще лучше, используйте ngKeypress и передайте событие $ в пользовательский фильтр.
Мартин
7
Лучший ответ +1. Зачем мне делать свою собственную директиву, если она есть, уже включена в Angular?
bFunc
179

Мой самый простой подход, использующий только угловую встроенную директиву:

ng-keypress, ng-keydownИли ng-keyup.

Обычно мы хотим добавить поддержку клавиатуры для чего-то, что уже обрабатывается с помощью ng-click.

например:

<a ng-click="action()">action</a>

Теперь давайте добавим поддержку клавиатуры.

запуск по клавише ввода:

<a ng-click="action()" 
   ng-keydown="$event.keyCode === 13 && action()">action</a>

по пробелу:

<a ng-click="action()" 
   ng-keydown="$event.keyCode === 32 && action()">action</a>

по пробелу или введите ключ:

<a ng-click="action()" 
   ng-keydown="($event.keyCode === 13 || $event.keyCode === 32) && action()">action</a>

если вы находитесь в современном браузере

<a ng-click="action()" 
   ng-keydown="[13, 32].includes($event.keyCode) && action()">action</a>

Подробнее о keyCode:
keyCode устарел, но хорошо поддерживается API, вместо этого вы можете использовать $ evevt.key в поддерживаемом браузере.
Подробнее смотрите в https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key

Эрик Чен
источник
1
секрет заключается в том, что перед выполнением метода необходимо выполнить $ event.which === 13 && action () - спасибо!
user12121234
1
«$ event.which» не работает для меня, но я нашел «$ event.keyCode», который работает.
Карл Адлер
event.which не определен в IE <9 при keydown и keyup.
Эрик Чен
2
"старые браузеры, такие как IE9" .. никогда не думал, что этот день настанет :)
Михня Белчин
1
Почему никто не обновил здесь фрагменты кода, чтобы использовать $ event.keyCode? Я бы отредактировал его сам, но по какой-то причине не могу.
Натан Хаззард
102

Еще одна простая альтернатива:

<input ng-model="edItem" type="text" 
    ng-keypress="($event.which === 13)?foo(edItem):0"/>

И альтернатива NG-UI:

<input ng-model="edItem" type="text" ui-keypress="{'enter':'foo(edItem)'}"/>
Родольфо Хорхе Немер Ногейра
источник
9
NG-UI это неоднозначно, вместо этого вы должны сказать «UI.Utils» или поделиться ссылкой: angular-ui.github.io/ui-utils
Пауло Оливейра
UI-Utils, кажется, устарела
cafesanu
19

Вот что я понял, когда создавал приложение с аналогичным требованием, для него не нужно писать директиву и относительно просто сказать, что оно делает:

<input type="text" ng-keypress="($event.charCode==13)?myFunction():return" placeholder="Will Submit on Enter">
marcinzajkowski
источник
3
Просто и эффективно.
Xplouder
15

Вы можете использовать ng-keydown = "myFunction ($ event)" в качестве атрибута.

<input ng-keydown="myFunction($event)" type="number">

myFunction(event) {
    if(event.keyCode == 13) {   // '13' is the key code for enter
        // do what you want to do when 'enter' is pressed :)
    }
}
Fineas
источник
5

HTML

<textarea id="messageTxt" 
    rows="5" 
    placeholder="Escriba su mensaje" 
    ng-keypress="keyPressed($event)" 
    ng-model="smsData.mensaje">
</textarea>

controller.js

$scope.keyPressed = function (keyEvent) {
    if (keyEvent.keyCode == 13) {
        alert('presiono enter');
        console.log('presiono enter');
    }
};
Хосе Дерли Ланчерос
источник
3

Вы также можете применить его к контроллеру родительского элемента. Этот пример можно использовать для выделения строки в таблице с помощью клавиш со стрелками вверх / вниз.

app.controller('tableCtrl', [ '$scope', '$element', function($scope, $element) {
  $scope.index = 0; // row index
  $scope.data = []; // array of items
  $scope.keypress = function(offset) {
    console.log('keypress', offset);
    var i = $scope.index + offset;
    if (i < 0) { i = $scope.data.length - 1; }
    if (i >= $scope.data.length) { i = 0; }
  };
  $element.bind("keydown keypress", function (event) {
    console.log('keypress', event, event.which);
    if(event.which === 38) { // up
      $scope.keypress(-1);
    } else if (event.which === 40) { // down
      $scope.keypress(1);
    } else {
      return;
    }
    event.preventDefault();
  });
}]);


<table class="table table-striped" ng-controller="tableCtrl">
<thead>
    <tr>
        <th ng-repeat="(key, value) in data[0]">{{key}}</th>
    </tr>
</thead>
<tbody>
    <tr ng-repeat="row in data track by $index" ng-click="draw($index)" ng-class="$index == index ? 'info' : ''">
        <td ng-repeat="(key, value) in row">{{value}}</td>
    </tr>
</tbody>
</table>

будет Фаррелл
источник
3

Попытка

ng-keypress="console.log($event)"
ng-keypress="alert(123)"

ничего не сделал для меня

Задушить образец на https://docs.angularjs.org/api/ng/directive/ngKeypress , который выполняет ng-keypress = "count = count + 1", работает.

Я нашел альтернативное решение, при котором нажатие Enter вызывает кнопку ng-click.

<input ng-model="..." onkeypress="if (event.which==13) document.getElementById('button').click()"/>
<button id="button" ng-click="doSomething()">Done</button>
snaran
источник
ng-keypress="console.log('foo')"у меня тоже не сработало, но если у вас так ng-keypress="fooMethod()"и у вас работает контроллер $scope.fooMethod = function() { console.log('fooMethod called'); }.
GraehamF
3
<!DOCTYPE html>
<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
<body>
<div ng-app="myApp" ng-controller="myCtrl">
Informe your name:<input type="text" ng-model="pergunta" ng-keypress="pressionou_enter($event)" ></input> 
<button ng-click="chamar()">submit</button>
<h1>{{resposta}}</h1> 
</div>
<script>
var app = angular.module('myApp', []);
//create a service mitsuplik
app.service('mitsuplik', function() {
    this.myFunc = function (parametro) {
        var tmp = ""; 
        for (var x=0;x<parametro.length;x++)
            {
            tmp = parametro.substring(x,x+1) + tmp;
            } 
        return tmp;
    }
});
//Calling our service
app.controller('myCtrl', function($scope, mitsuplik) { 
  $scope.chamar = function() { 
        $scope.resposta = mitsuplik.myFunc($scope.pergunta); 
    };
  //if mitsuplik press [ENTER], execute too
  $scope.pressionou_enter = function(keyEvent) {
             if (keyEvent.which === 13) 
                { 
                $scope.chamar();
                }

    }
});
</script>
</body>
</html>
Маркус Поли
источник
2

Это продолжение ответа от EpokK.

У меня была та же проблема с необходимостью вызывать функцию области видимости, когда ввод вводится в поле ввода. Однако я также хотел передать значение поля ввода в указанную функцию. Это мое решение:

app.directive('ltaEnter', function () {
return function (scope, element, attrs) {
    element.bind("keydown keypress", function (event) {
        if(event.which === 13) {
          // Create closure with proper command
          var fn = function(command) {
            var cmd = command;
            return function() {
              scope.$eval(cmd);
            };
          }(attrs.ltaEnter.replace('()', '("'+ event.target.value +'")' ));

          // Apply function
          scope.$apply(fn);

          event.preventDefault();
        }
    });
};

});

Использование в HTML выглядит следующим образом:

<input type="text" name="itemname" lta-enter="add()" placeholder="Add item"/>

Престижность EpokK за его ответ.

tassaert.l
источник
<input type="text" name="itemname" ng-model="item.itemname" lta-enter="add(item.itemname)" placeholder="Add item"/>
айканадал
1

Что насчет этого?:

<form ng-submit="chat.sendMessage()">
    <input type="text" />
    <button type="submit">
</form>

Теперь, когда вы нажимаете клавишу ввода после того, как что-то записали в свой ввод, форма знает, как с этим справиться.

juanmorschrott
источник
Как / где chat.sendMessage()определяется
Аарон Макмиллин
0

Пример кода, который я сделал для своего проекта. В основном вы добавляете теги к своей сущности. Представьте, что у вас есть введенный текст, при вводе имени тега вы получаете выпадающее меню с предварительно загруженными тегами на выбор, вы перемещаетесь со стрелками и выбираете с помощью Enter:

HTML + AngularJS v1.2.0-rc.3

    <div>
        <form ng-submit="addTag(newTag)">
            <input id="newTag" ng-model="newTag" type="text" class="form-control" placeholder="Enter new tag"
                   style="padding-left: 10px; width: 700px; height: 33px; margin-top: 10px; margin-bottom: 3px;" autofocus
                   data-toggle="dropdown"
                   ng-change="preloadTags()"
                   ng-keydown="navigateTags($event)">
            <div ng-show="preloadedTags.length > 0">
                <nav class="dropdown">
                    <div class="dropdown-menu preloadedTagPanel">
                        <div ng-repeat="preloadedTag in preloadedTags"
                             class="preloadedTagItemPanel"
                             ng-class="preloadedTag.activeTag ? 'preloadedTagItemPanelActive' : '' "
                             ng-click="selectTag(preloadedTag)"
                             tabindex="{{ $index }}">
                            <a class="preloadedTagItem"
                               ng-class="preloadedTag.activeTag ? 'preloadedTagItemActive' : '' "
                               ng-click="selectTag(preloadedTag)">{{ preloadedTag.label }}</a>
                        </div>
                    </div>
                </nav>
            </div>
        </form>
    </div>

Controller.js

$scope.preloadTags = function () {
    var newTag = $scope.newTag;
    if (newTag && newTag.trim()) {
        newTag = newTag.trim().toLowerCase();

        $http(
            {
                method: 'GET',
                url: 'api/tag/gettags',
                dataType: 'json',
                contentType: 'application/json',
                mimeType: 'application/json',
                params: {'term': newTag}
            }
        )
            .success(function (result) {
                $scope.preloadedTags = result;
                $scope.preloadedTagsIndex = -1;
            }
        )
            .error(function (data, status, headers, config) {
            }
        );
    } else {
        $scope.preloadedTags = {};
        $scope.preloadedTagsIndex = -1;
    }
};

function checkIndex(index) {
    if (index > $scope.preloadedTags.length - 1) {
        return 0;
    }
    if (index < 0) {
        return $scope.preloadedTags.length - 1;
    }
    return index;
}

function removeAllActiveTags() {
    for (var x = 0; x < $scope.preloadedTags.length; x++) {
        if ($scope.preloadedTags[x].activeTag) {
            $scope.preloadedTags[x].activeTag = false;
        }
    }
}

$scope.navigateTags = function ($event) {
    if (!$scope.newTag || $scope.preloadedTags.length == 0) {
        return;
    }
    if ($event.keyCode == 40) {  // down
        removeAllActiveTags();
        $scope.preloadedTagsIndex = checkIndex($scope.preloadedTagsIndex + 1);
        $scope.preloadedTags[$scope.preloadedTagsIndex].activeTag = true;
    } else if ($event.keyCode == 38) {  // up
        removeAllActiveTags();
        $scope.preloadedTagsIndex = checkIndex($scope.preloadedTagsIndex - 1);
        $scope.preloadedTags[$scope.preloadedTagsIndex].activeTag = true;
    } else if ($event.keyCode == 13) {  // enter
        removeAllActiveTags();
        $scope.selectTag($scope.preloadedTags[$scope.preloadedTagsIndex]);
    }
};

$scope.selectTag = function (preloadedTag) {
    $scope.addTag(preloadedTag.label);
};

CSS + Bootstrap v2.3.2

.preloadedTagPanel {
    background-color: #FFFFFF;
    display: block;
    min-width: 250px;
    max-width: 700px;
    border: 1px solid #666666;
    padding-top: 0;
    border-radius: 0;
}

.preloadedTagItemPanel {
    background-color: #FFFFFF;
    border-bottom: 1px solid #666666;
    cursor: pointer;
}

.preloadedTagItemPanel:hover {
    background-color: #666666;
}

.preloadedTagItemPanelActive {
    background-color: #666666;
}

.preloadedTagItem {
    display: inline-block;
    text-decoration: none;
    margin-left: 5px;
    margin-right: 5px;
    padding-top: 5px;
    padding-bottom: 5px;
    padding-left: 20px;
    padding-right: 10px;
    color: #666666 !important;
    font-size: 11px;
}

.preloadedTagItem:hover {
    background-color: #666666;
}

.preloadedTagItemActive {
    background-color: #666666;
    color: #FFFFFF !important;
}

.dropdown .preloadedTagItemPanel:last-child {
    border-bottom: 0;
}
Дмитрий Алгазин
источник
2
Я думаю, что это противное решение. Контроллер не должен обрабатывать такие вещи, как нажатия клавиш.
Майя Катрин Андерсен
5
Этот ответ содержит много «шума», в некотором смысле, содержит много разметки, которая, насколько я могу видеть с первого взгляда, не относится к актуальному вопросу. Может быть более кратким / полезным сжать код в ответе и привести полный пример в gist / jsfiddle / plnkr.
Корнелиус
1
@MartinAndersen, где нужно обрабатывать нажатие клавиш в угловом приложении?
Emanegux
1
Когда я смотрю на это сейчас, это выглядит хорошо. Это в основном то, как нажатия клавиш всегда обрабатывались с помощью модели событий JS.
Майя Катрин Андерсен
0

Я немного опоздал .. но я нашел более простое решение, используя auto-focus.. Это может быть полезно для кнопок или других, когда выдает dialog:

<button auto-focus ng-click="func()">ok</button>

Это должно быть хорошо, если вы хотите нажать кнопку onпробела или Enter кликов.

Абделла Алауи
источник
вопрос это о прессе войти и сделать что-то.
BlaShadow
0

вот моя директива:

mainApp.directive('number', function () {
    return {
        link: function (scope, el, attr) {
            el.bind("keydown keypress", function (event) {
                //ignore all characters that are not numbers, except backspace, delete, left arrow and right arrow
                if ((event.keyCode < 48 || event.keyCode > 57) && event.keyCode != 8 && event.keyCode != 46 && event.keyCode != 37 && event.keyCode != 39) {
                    event.preventDefault();
                }
            });
        }
    };
});

Применение:

<input number />
WtFudgE
источник
0

Вы можете использовать ng-keydown, ng-keyup, ng-press, такие как эта.

чтобы активировать функцию:

   <input type="text" ng-keypress="function()"/>

или если у вас есть одно условие, например, когда он нажимает клавишу escape (27 - это код клавиши для выхода)

 <form ng-keydown=" event.which=== 27?cancelSplit():0">
....
</form>
Eassa Nassar
источник
0

Я думаю, что использование document.bind немного более элегантно

constructor($scope, $document) {
  var that = this;
  $document.bind("keydown", function(event) {
    $scope.$apply(function(){
      that.handleKeyDown(event);
    });
  });
}

Чтобы получить документ для конструктора контроллера:

controller: ['$scope', '$document', MyCtrl]
FreshPow
источник
0
(function(angular) {
  'use strict';
angular.module('dragModule', [])
  .directive('myDraggable', ['$document', function($document) {
    return {
      link: function(scope, element, attr) {
         element.bind("keydown keypress", function (event) {
           console.log('keydown keypress', event.which);
            if(event.which === 13) {
                event.preventDefault();
            }
        });
      }
    };
  }]);
})(window.angular);
Mukundhan
источник
0

Все, что вам нужно сделать, чтобы получить событие является следующее:

console.log(angular.element(event.which));

Директива может сделать это, но это не так, как вы это делаете.

Konkret
источник