如何在 AngularJS 中使用按键事件?
Posted
技术标签:
【中文标题】如何在 AngularJS 中使用按键事件?【英文标题】:How to use a keypress event in AngularJS? 【发布时间】:2013-07-02 11:43:57 【问题描述】:我想在下面的文本框中捕捉回车键按下事件。为了更清楚,我使用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
【问题讨论】:
输入是否在表单内? 不..它在一张桌子上!! github.com/ccampbell/mousetrap 帮助了。以防万一寻找图书馆。 【参考方案1】:你需要添加一个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>
【讨论】:
@DerekAdair 该指令绑定到它所归属的元素的keydown
和keypress
事件。收到事件后,在 $apply
块内评估提供的表达式。
更安全地定义这样的键:var key = typeof event.which === "undefined" ? event.keyCode : event.which;
,只要不是每个浏览器都使用 event.which。在此处查看 cmets:***.com/a/4471635/2547632
我还会在绑定测试中添加keyup
还请注意,不建议使用 ng 前缀,因为这可能与未来的 ng-* 指令发生冲突。改用你自己的
别忘了销毁你的绑定:scope.$on('$destroy', function() element.unbind('keydown'); )【参考方案2】:
另一种方法是使用标准指令ng-keypress="myFunct($event)"
然后在你的控制器中你可以拥有:
...
$scope.myFunct = function(keyEvent)
if (keyEvent.which === 13)
alert('I am an alert');
...
【讨论】:
为了节省其他人一些时间,ng-keypress
似乎不是 angular 1.0.x 的一部分,但ui-keypress
(调用语义略有不同)可用:angular-ui.github.io/ui-utils跨度>
我认为上面的评论是针对不同的答案。 (仅供参考。)
Martin 这实际上是一个控制器的功能:处理 UI 事件。
更好的是,使用 ngKeypress 并将 $event 传递给自定义过滤器。
最佳答案 +1。如果有一个指令,我为什么要制定自己的指令,已经包含在 Angular 中?【参考方案3】:
我只使用角度内置指令的最简单方法:
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中查看更多信息
【讨论】:
秘密是要执行的方法之前的条件 $event.which === 13 && action() - 谢谢! '$event.which' 对我不起作用,但我发现'$event.keyCode' 起作用了。 event.which is undefined in IE “像 IE9 这样的旧浏览器”.. 没想到这一天会到来 :) 为什么没有人更新这里的代码 sn-ps 以使用 $event.keyCode 呢?我会自己编辑它,但由于某种原因我无法编辑。【参考方案4】:另一个简单的选择:
<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)'"/>
【讨论】:
ng-ui 有歧义,你应该说“UI.Utils”或分享链接:angular-ui.github.io/ui-utils ui-utils 似乎已被弃用【参考方案5】:这是我在构建具有类似要求的应用程序时发现的, 它不需要编写指令,而且说明它的作用相对简单:
<input type="text" ng-keypress="($event.charCode==13)?myFunction():return" placeholder="Will Submit on Enter">
【讨论】:
简单有效。【参考方案6】:您可以使用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');
;
【讨论】:
【参考方案8】:您也可以将其应用于父元素上的控制器。此示例可用于通过按向上/向下箭头键突出显示表格中的一行。
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>
【讨论】:
【参考方案9】:尝试
ng-keypress="console.log($event)"
ng-keypress="alert(123)"
没有为我做任何事情。
Strangley 在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');
确实有效。【参考方案10】:
<!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>
【讨论】:
【参考方案11】:这是对 EpokK 答案的扩展。
当在输入字段上按下 enter 时,我遇到了同样的问题,即必须调用作用域函数。不过,我也想将 输入字段的值 传递给指定的函数。这是我的解决方案:
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 的回答。
【讨论】:
<input type="text" name="itemname" ng-model="item.itemname" lta-enter="add(item.itemname)" placeholder="Add item"/>
【参考方案12】:
这个呢?
<form ng-submit="chat.sendMessage()">
<input type="text" />
<button type="submit">
</form>
现在,当您在输入内容中输入内容后按下回车键时,表单知道如何处理它。
【讨论】:
chat.sendMessage()
的定义方式/位置【参考方案13】:
我为我的项目所做的一些代码示例。 基本上,您将标签添加到您的实体。 假设您输入了文本,在输入标签名称时,您会看到带有预加载标签的下拉菜单可供选择,您使用箭头导航并使用 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;
【讨论】:
我认为这是一个讨厌的解决方案。控制器不应处理诸如按键之类的 UI 事务。 这个答案包含很多“噪音”,从某种意义上说,包含很多标记——据我一目了然——与手头的实际问题无关.压缩答案中的代码并在 gist/jsfiddle/plnkr 中提供完整示例可能更简洁/有用。 @MartinAndersen,在 Angular 应用程序中应该在哪里处理按键? 当我现在看它时,它看起来还不错。这基本上是 JS 事件模型一直以来处理按键的方式。【参考方案14】:我有点晚了 .. 但我找到了一个使用 auto-focus
的更简单的解决方案 .. 这对于弹出 dialog
时的按钮或其他内容可能很有用:
<button auto-focus ng-click="func()">ok</button>
如果你想按下按钮 on
Space 或 Enter clicks 应该没问题。
【讨论】:
关于按回车做某事的问题。【参考方案15】:这是我的指令:
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 />
【讨论】:
【参考方案16】:您可以使用 ng-keydown 、 ng-keyup 、 ng-press 等。
触发函数:
<input type="text" ng-keypress="function()"/>
或者,如果您有一种情况,例如当他按下转义键时(27 是关键 转义代码)
<form ng-keydown=" event.which=== 27?cancelSplit():0">
....
</form>
【讨论】:
【参考方案17】:我认为使用 document.bind 更优雅一些
constructor($scope, $document)
var that = this;
$document.bind("keydown", function(event)
$scope.$apply(function()
that.handleKeyDown(event);
);
);
将文档获取到控制器构造函数:
controller: ['$scope', '$document', MyCtrl]
【讨论】:
【参考方案18】:(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);
【讨论】:
【参考方案19】:您只需执行以下操作即可:
console.log(angular.element(event.which));
指令可以做到这一点,但这不是你如何做到的。
【讨论】:
以上是关于如何在 AngularJS 中使用按键事件?的主要内容,如果未能解决你的问题,请参考以下文章
如何在python中运行另一个程序的python中模拟按键事件