如何在AngularJS中使用按键事件?

428

我希望能够捕获下面文本框的回车键按下事件。为了更清晰,我使用 ng-repeat 来填充 tbody。以下是 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
不,它在一个表格中! - Venkata K. C. Tata
如果你正在寻找一个库,那么 https://github.com/ccampbell/mousetrap 可以帮助你。 - Gokul
19个回答

817

你需要添加一个像这样的 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>

7
@DerekAdair 指令与分配的元素的keydownkeypress事件绑定。当接收到事件时,提供的表达式将在$apply块内进行评估。 - Pete Martin
7
如此定义键盘事件的key变量更为安全:var key = typeof event.which === "undefined" ? event.keyCode : event.which;,只要不是所有浏览器都使用event.which。参考这里的评论:https://dev59.com/o2855IYBdhLWcg3wNhd1#4471635 - Gabriel
3
我会在绑定测试中添加 keyup - user1713964
59
请注意,不建议使用以"ng"为前缀的指令,因为这可能与未来的"ng-*"指令发生冲突。请改用其他前缀。 - Marius Balčytis
3
不要忘记销毁你的绑定: scope.$on('$destroy',function(){ element.unbind('keydown'); }) - nawlbergs
显示剩余15条评论

361

另一种选择是使用标准指令 ng-keypress="myFunct($event)"

然后在您的控制器中,您可以这样编写:

...

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

...

19
为了节省其他人的时间,需要说明的是 ng-keypress 不是 Angular 1.0.x 的一部分,但是可以使用带有稍微不同调用语义的 ui-keypress :http://angular-ui.github.io/ui-utils/。请注意,这不是解释。 - Cebjyre
1
我认为上面的评论是针对另一个答案的(仅供参考)。 - Cornelius
Martin,这实际上是控制器的功能:处理用户界面事件。 - Trevor de Koekkoek
5
更好的做法是使用ngKeypress,并将$event传递给自定义过滤器。 - Martin
8
为什么我需要编写自己的指令,如果Angular已经包含了一个指令呢?最佳答案+1。 - bFunc
显示剩余4条评论

187

我使用 Angular 内置指令的最简单方法:

ng-keypressng-keydownng-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,您可以在支持的浏览器中使用$event.key。
详情请参见https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key


1
秘诀在于执行方法之前的条件判断 $event.which === 13 && action() - 谢谢! - user12121234
1
"$event.which" 对我不起作用,但我发现 "$event.keyCode" 是有效的。 - Karl Adler
在IE<9的keydown和keyup事件中,event.which未定义。 - Eric Chen
2
老旧的浏览器,比如IE9,从来没有想过这一天会到来 :) - Mihnea Belcin
1
为什么没有人更新这里的代码片段来使用$event.keyCode呢?我想自己编辑,但由于某些原因无法编辑。 - Nathan Hazzard

104

另一个简单的选择:

<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”或分享链接:http://angular-ui.github.io/ui-utils/。 - Paulo Oliveira
ui-utils 似乎已经被弃用。 - cafesanu

19

当我构建一个具有类似要求的应用程序时,我发现了以下内容,它不需要编写指令且相对简单易懂:

<input type="text" ng-keypress="($event.charCode==13)?myFunction():return" placeholder="Will Submit on Enter">

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 :)
    }
}

7

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

4

您还可以将其应用于父元素上的控制器。通过按上/下箭头键,可以将此示例用于突出显示表格中的一行。

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

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>

ng-keypress="console.log('foo')" 对我也不起作用,但如果你使用ng-keypress="fooMethod()"并在你的控制器中写上 $scope.fooMethod = function() { console.log('fooMethod called'); } 就可以工作了。 - GraehamF

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接