【问题标题】:How to use a keypress event in AngularJS?如何在 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 
}

【问题讨论】:

标签: angularjs angularjs-directive angular-ui


【解决方案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 该指令绑定到它所归属的元素的keydownkeypress 事件。收到事件后,在 $apply 块内评估提供的表达式。
  • 更安全地定义这样的键:var key = typeof event.which === "undefined" ? event.keyCode : event.which;,只要不是每个浏览器都使用 event.which。在此处查看 cmets:stackoverflow.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-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,您可以在支持的浏览器中使用 $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)'}"/>

【讨论】:

【解决方案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 的回答。

          【讨论】:

          • &lt;input type="text" name="itemname" ng-model="item.itemname" lta-enter="add(item.itemname)" placeholder="Add item"/&gt;
          【解决方案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 时的按钮或其他内容可能很有用:

          &lt;button auto-focus ng-click="func()"&gt;ok&lt;/button&gt;

          如果你想按下按钮 onSpace 或 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));
                  

                  指令可以做到这一点,但这不是你如何做到的。

                  【讨论】:

                    猜你喜欢
                    • 2012-11-13
                    • 1970-01-01
                    • 2023-03-09
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2023-03-03
                    • 1970-01-01
                    • 1970-01-01
                    相关资源
                    最近更新 更多